• 面向对象


    '''
    class Person:   #类名
        country = "China"  # 创建这类的属性 #类属性:静态属性
        def __init__(self,name,blood,aggr,sex,money): #初始化方法,self是对象,必须传的参数
            self.name = name  #对象的属性
            self.blood = blood
            self.aggr = aggr
            self.sex = sex
            self.money = money
        def da(self,dog):    #方法,一般情况下必须传self参数,且必须写在第一个,后面还可以传其他参数,是自由的
            dog.blood -= self.aggr
            print("%s被%s打了,掉了%s的血"%(dog.name,self.name,self.aggr))
        def get_wuqi(self,wuqi):
            if self.money >= wuqi.price:
                self.money -= wuqi.price
                self.aggr += wuqi.aggr
                self.wuqi = wuqi
            else:
                print("余额不足,请充值")
    class Dog:
        def __init__(self,name,blood,aggr,kind):
            self.name = name
            self.blood = blood
            self.aggr = aggr
            self.kind = kind
        def yao(self,person):
            person.blood -= self.aggr
            print("%s被%s打了,掉了%s的血" % (person.name, self.name, self.aggr))
    class Wuqi:
        def __init__(self,name,price,aggr,njd):
            self.name = name
            self.price = price
            self.aggr = aggr
            self.njd = njd
        def dazhao(self,dog):
            if self.njd >0:
                dog.blood -= self.aggr*2
                self.njd -= 1
            if dog.blood>0:
                print("%s被打死了"%(dog.name))
    print(Person.country)    #类名 可以查看类中的属性,不需要实例化就可以查看
    xiaoli = Person("狗蛋",1000,100,"男",0)   #实例化 xiali是对象
    zhu = Dog("猪猪侠",2000,10,"泰迪")        #对象 = 类名()
    wuqi = Wuqi("打狗棒",1000,200,10)
    
    print(xiaoli.__dict__) #查看所有属性
    print(zhu.__dict__["name"]) #查看zhu的name属性值 可以看作是一个字典,属性对应的相当于字典的
                    # "key",而属性值相当于字典的"value",对象的属性操作,可以适用字典的操作
    print(wuqi.__dict__)
    xiaoli.da(zhu)    #调用方法     类名.
    zhu.yao(xiaoli)
    xiaoli.get_wuqi(wuqi)
    xiaoli.money += 1000
    xiaoli.get_wuqi(wuqi)
    xiaoli.da(zhu)
    xiaoli.wuqi.dazhao(zhu)
    print(zhu.blood)   #查看属性值
    print(wuqi.njd)
    View Code

    组合 :一个对象的属性值是另外一个类的对象

    xiaoli.wuqi 是 Wuqi类的对象

    from math import pi
    class Circle:
        def __init__(self,r):
            self.r = r
        def area(self):
            return self.r**2 * pi
        def perimeter(self):
            return 2*pi*self.r
    
    class Ring:
        def __init__(self,outside_r,inside_r):
            self.outside_c = Circle(outside_r)
            self.inside_c = Circle(inside_r)
        def area(self):
            return self.outside_c.area() - self.inside_c.area()
        def perimeter(self):
            return self.outside_c.perimeter()+self.inside_c.perimeter()
    
    # ring = Ring(20,10)
    # print(ring.area())
    # print(ring.perimeter())
    组合练习
    # 创建一个老师类
    # 老师有生日
    # 生日也可以是一个类
    # 组合
    class Birthday:
        def __init__(self,year,month,day):
            self.year = year
            self.month = month
            self.day = day
    
    class Course:
        def __init__(self,course_name,period,price):
            self.name = course_name
            self.period = period
            self.price = price
    
    class Teacher:
        def __init__(self,name,age,sex,birthday):
            self.name = name
            self.age = age
            self.sex = sex
            self.birthday =birthday
            self.course = Course('python','6 month',2000)
    
    b = Birthday(2018,1,16)
    egg = Teacher('egon',0,'',b)
    print(egg.name)
    print(egg.birthday.year)
    print(egg.birthday.month)
    print(egg.course.price)
    View Code

    ## 对象 = 类名()         》实例化
    # 过程:
      # 类名() 首先 会创造出一个对象,创建了一个self变量
      # 调用init方法,类名括号里的参数会被这里接收
      # 执行init方法
      # 返回self
    # 对象能做的事:
      # 查看属性
      # 调用方法
      # __dict__ 对于对象的增删改查操作都可以通过字典的语法进行
    # 类名能做的事:
      # 实例化
      # 调用方法 : 只不过要自己传递self参数
      # 调用类中的属性,也就是调用静态属性
      # __dict__ 对于类中的名字只能看 不能操作
    # 定义类
      # class
      # 函数 : 方法 动态属性 # 类中可以定义方法,方法都有一个必须传的参数self
      # 变量 : 类属性 静态属性 # 类中可以定义静态属性
    # __init__方法 初始化方法
      # python帮我们创建了一个对象self
      # 每当我们调用类的时候就会自动触发这个方法。默认传self
      # 在init方法里面可以对self进行赋值
    # self是什么 self拥有属性都属于对象
      #在类的内部,self就是一个对象
      # xiaoli = Person() #实例化
      # xiaoli.da(zhu) == Person.da(xiaoli,zhu) #对象调用方法:对象名.方法名 == 类名.方法名(对象名)
    # 实例化
      # 对象 = 类(参数是init方法的)
      # 实例、对象 完全没有区别
    # 对象查看属性
      # 对象.属性名
      # 对象调用方法
      # 对象.方法名(参数) #类名.方法名(对象名,参数)

    一:我们定义的类的属性到底存到哪里了?有两种方式查看
    dir(类名):查出的是一个名字列表
    类名.__dict__:查出的是一个字典,key为属性名,value为属性值
    
    二:特殊的类属性
    类名.__name__# 类的名字(字符串)
    类名.__doc__# 类的文档字符串
    类名.__base__# 类的第一个父类(在讲继承时会讲)
    类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
    类名.__dict__# 类的字典属性
    类名.__module__# 类定义所在的模块
    类名.__class__# 实例对应的类(仅新式类中)
    类属性的补充
    # class Course:
    #     language = "Chinese"
    #     def __init__(self,teacher,course_name,period,price):
    #         self.teacher = teacher
    #         self.course_name = course_name
    #         self.period = period
    #         self.price = price
    # print(Course.language)    #  查看类属性  Chinese
    # Course.language = "English"  #修改类的属性  #类名.属性 = 新的属性名
    # print(Course.language)   #  English
    # python = Course("xiaoli","python","6 months",20000)
    # linux = Course("zhu","linux","3 montths",13000)
    # print(python.language)     # English
    # python.language = "Chinese"   #相当于给对象python 添加了一个language属性
    # print(python.language)    # Chinese
    # print(linux.language)      #对象调用类的静态属性    # English
    
    # class Course:
    #     language = ["Chinese"]
    #     def __init__(self,teacher,course_name,period,price,):
    #         self.teacher = teacher
    #         self.course_name = course_name
    #         self.period = period
    #         self.price = price
    # print(Course.language)    #  查看类属性  ['Chinese']
    # python = Course("xiaoli","python","6 months",20000)
    # linux = Course("zhu","linux","3 montths",13000)
    # print(python.language)  # ['Chinese']
    # python.language[0] = "English"
    # print(python.language)      #  ['English']
    # print(linux.language)         #  ['English']
    #
    # # 类中的静态变量 可以被对象和类调用
    # # 对于不可变数据类型来说,类变量最好用类名操作
    # # 对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的
    静态属性的补充

    继承

    class Animal:
    #     def __init__(self,name,aggr,hp):
    #         self.name = name
    #         self.aggr = aggr
    #         self.hp = hp
    #     def eat(self):
    #         print("吃药回血")
    #         self.hp += 100
    # class Dog(Animal):
    #     def __init__(self,name,aggr,hp,kind):
    #         Animal.__init__(self,name,aggr,hp)
    #         self.kind = kind    #派生属性
    #     def eat(self):    #如果既想实现新的功能也想使用父类原本的功能,还需要在子类中再调用父类
    #         Animal.eat(self)
    #         self.teeth = 2
    #     def yao(self,person):        #派生方法
    #         person.hp -= self.aggr
    # class Person(Animal):
    #     def __init__(self,name,aggr,hp,sex):
    #         super().__init__(name,aggr,hp)    #等同于Animal.__init__(self,name,aggr,hp),新式类才有,py3 都是新式类
    #         self.sex = sex
    #     def gongji(self,dog):
    #         dog.hp -= self.aggr
    # p = Person("小利",100,100,"男")
    # d = Dog("疯狗",2,500,"泰迪")
    # print(Person.__bases__)  #查看 Person类的继承情况 #(<class '__main__.Animal'>,)
    View Code

    # # python3 -新式类# 没有继承父类默认继承object
    # 父类中没有的属性 在子类中出现 叫做派生属性
    # 父类中没有的方法 在子类中出现 叫做派生方法
    # 只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
    # 如果父类 子类都有 用子类的
    # 如果还想用父类的,单独调用父类的:
    # 父类名.方法名 需要自己传self参数
    # super().方法名 不需要自己传self
    # 正常的代码中 单继承 === 减少了代码的重复
    # 继承表达的是一种 子类是父类的关系

    多继承

     #class F:
    #     def f(self):
    #         print("F")
    # class C(F):
    #     def f(self):
    #         print("C")
    # class D(F):
    #     def f(self):
    #         print("D")
    # class B(D,C):
    #     def f(self):
    #         print("B")
    # b = B()
    # b.f() # B  如果B类里的代码用pass,则找类D中的值,D离B进   B>D>C>A    广度优先 
    砖石
    # class E:
    #     def f(self):
    #         print("E")
    # class C(E):
    #     def f(self):
    #         print("C")
    # class D:
    #     def f(self):
    #         print("D")
    # class B(D):
    #     def f(self):
    #         print("B")
    # class A(B,C):
    #     def f(self):
    #         print("A")
    # a = A()
    # a.f() #  A  #  A>B>D>C>E 
    漏斗
    # class E:
    #     def f(self):
    #         print("E")
    # class C(E):
    #     def f(self):
    #         print("C")
    # class D:
    #     def f(self):
    #         print("D")
    # class B(D):
    #     def f(self):
    #         print("B")
    # class A(B,C):
    #     def f(self):
    #         print("A")
    # a = A()
    # a.f() #  A  #  A>B>D>C>E 
    乌龟

    继承原理

    python到底是如何实现继承的,对于你定义的每一个类,python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的所有基类的线性顺序列表,例如

    >>> A.mro() #等同于A.__mro__
    [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <class 'object'>]

    为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
    而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
    1.子类会先于父类被检查
    2.多个父类会根据它们在列表中的顺序被检查
    3.如果对下一个类存在两个合法的选择,选择第一个父类

    继承小结

    继承的作用

    减少代码的重用
    提高代码可读性
    规范编程模式

    几个名词

    抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
    继承:子类继承了父类的方法和属性
    派生:子类在父类方法和属性的基础上产生了新的方法和属性

    抽象类与接口类

    复制代码
    1.多继承问题
    在继承抽象类的过程中,我们应该尽量避免多继承;
    而在继承接口的时候,我们反而鼓励你来多继承接口
    
    
    2.方法的实现
    在抽象类中,我们可以对一些抽象方法做出基础实现;
    而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
    复制代码

    钻石继承

    新式类:广度优先
    经典类:深度优先
    # class A(object):
    #     def func(self): print('A')
    #
    # class B(A):
    #     def func(self):
    #         super().func()
    #         print('B')
    #
    # class C(A):
    #     def func(self):
    #         super().func()
    #         print('C')
    #
    # class D(B,C):
    #     def func(self):
    #         super().func()
    #         print('D')
    # d = D()        #A>C>B>D
    # d.func()
    # # super 只在python3中存在
    # # super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的
    super()

    继承有两种用途:

    一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)  

    二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

    #接口类 单继承
    # from abc import abstractmethod,ABCMeta
    # class Pay(metaclass=ABCMeta):  #元类
    #     @abstractmethod
    #     def pay(self,money):
    #         pass
    # # 规范 :接口类或者抽象类都可以
    # # 接口类 支持多继承,接口类中的所有的方法都必须不能实现 —— java演化来的
    # # 抽象类 不支持多继承,抽象类中方法可以有一些代码的实现 —— java
    # class Wechat(Pay):
    #     def pay(self,money):
    #         print("已经用微信支付了%s元"%money)
    # class Ali(Pay):
    #     def pay(self,money):
    #         print("已经用支付宝支付了%s元"%money)
    # class Apple(Pay):
    #     def pay(self,money):
    #         print("已经用苹果支付了%s元"%money)
    # def s(pay_obj,money):  #统一支付入口
    #     pay_obj.pay(money)
    # ali = Ali()
    # ali.pay(200)
    # we = Wechat()
    # we.pay(1)
    # s(ali,10)
    # s(we,123)
    
    #接口类 多继承
    # from abc import abstractmethod,ABCMeta
    # class Swim_Animal(metaclass=ABCMeta):
    #     @abstractmethod
    #     def swim(self):
    #        pass
    # class Walk_Animal(metaclass=ABCMeta):
    #     @abstractmethod
    #     def walk(self):
    #         pass
    # class Fly_Animal(metaclass=ABCMeta):
    #     @abstractmethod
    #     def fly(self):
    #         pass
    #
    # class Tiger(Swim_Animal,Walk_Animal):
    #     def swim(self):
    #         print("f")
    #     def walk(self):
    #         pass
    #     def h(self):
    #         print("s")
    # t = Tiger()
    # t.swim()
    
    
    # 接口类  刚好满足接口隔离原则 面向对象开发的思想 规范
    View Code

    抽象类

    什么是抽象类

        与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

    为什么要有抽象类

        如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类是从一堆中抽取相同的内容而来的,内容包括数据属性和函数属性。

      比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。

        从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

      从实现角度来看,抽象类与普通类的不同之处在于:抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的,即将揭晓答案

    在python中实现抽象类

    复制代码
    #一切皆文件
    import abc #利用abc模块实现抽象类
    
    class All_file(metaclass=abc.ABCMeta):
        all_type='file'
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def read(self):
            '子类必须定义读功能'
            pass
    
        @abc.abstractmethod #定义抽象方法,无需实现功能
        def write(self):
            '子类必须定义写功能'
            pass
    
    # class Txt(All_file):
    #     pass
    #
    # t1=Txt() #报错,子类没有定义抽象方法
    
    class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    
    wenbenwenjian=Txt()
    
    yingpanwenjian=Sata()
    
    jinchengwenjian=Process()
    
    #这样大家都是被归一化了,也就是一切皆文件的思想
    wenbenwenjian.read()
    yingpanwenjian.write()
    jinchengwenjian.read()
    
    print(wenbenwenjian.all_type)
    print(yingpanwenjian.all_type)
    print(jinchengwenjian.all_type)
    复制代码

    抽象类与接口类

    抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

    抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 

    在python中,并没有接口类这种东西,即便不通过专门的模块定义接口,我们也应该有一些基本的概念。

    1.多继承问题

    在继承抽象类的过程中,我们应该尽量避免多继承;
    而在继承接口的时候,我们反而鼓励你来多继承接口

    接口隔离原则:
    使用多个专门的接口,而不使用单一的总接口。即客户端不应该依赖那些不需要的接口。

    2.方法的实现

    在抽象类中,我们可以对一些抽象方法做出基础实现;
    而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现


    # 抽象类 : 规范
    # 一般情况下 单继承 能实现的功能都是一样的,所以在父类中可以有一些简单的基础实现
    # 多继承的情况 由于功能比较复杂,所以不容易抽象出相同的功能的具体实现写在父类中


    # 抽象类还是接口类 : 面向对象的开发规范 所有的接口类和抽象类都不能实例化
    # java :
    # java里的所有类的继承都是单继承,所以抽象类完美的解决了单继承需求中的规范问题
    # 但对于多继承的需求,由于java本身语法的不支持,所以创建了接口Interface这个概念来解决多继承的规范问题

    # python
    # python中没有接口类 :
    # python中自带多继承 所以我们直接用class来实现了接口类
    # python中支持抽象类 : 一般情况下 单继承 不能实例化
    # 且可以实现python代码

    多态

    多态

    多态指的是一类事物有多种形态

    动物有多种形态:人,狗,猪

    复制代码
    import abc
    class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
        @abc.abstractmethod
        def talk(self):
            pass
    
    class People(Animal): #动物的形态之一:人
        def talk(self):
            print('say hello')
    
    class Dog(Animal): #动物的形态之二:狗
        def talk(self):
            print('say wangwang')
    
    class Pig(Animal): #动物的形态之三:猪
        def talk(self):
            print('say aoao')
    复制代码

    文件有多种形态:文本文件,可执行文件

    复制代码
    import abc
    class File(metaclass=abc.ABCMeta): #同一类事物:文件
        @abc.abstractmethod
        def click(self):
            pass
    
    class Text(File): #文件的形态之一:文本文件
        def click(self):
            print('open file')
    
    class ExeFile(File): #文件的形态之二:可执行文件
        def click(self):
            print('execute file')
    复制代码

    多态性

    一 什么是多态动态绑定(在继承的背景下使用时,有时也称为多态性)

    多态性是指在不考虑实例类型的情况下使用实例

    复制代码
    在面向对象方法中一般是这样表述多态性:
    向不同的对象发送同一条消息(!!!obj.func():是调用了obj的方法func,又称为向obj发送了一条消息func),不同的对象在接收时会产生不同的行为(即方法)。
    也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
    
    比如:老师.下课铃响了(),学生.下课铃响了(),老师执行的是下班操作,学生执行的是放学操作,虽然二者消息一样,但是执行的效果不同
    复制代码

    多态性

    复制代码
    peo=People()
    dog=Dog()
    pig=Pig()
    
    #peo、dog、pig都是动物,只要是动物肯定有talk方法
    #于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
    peo.talk()
    dog.talk()
    pig.talk()
    
    #更进一步,我们可以定义一个统一的接口来使用
    def func(obj):
        obj.talk()
    复制代码

    鸭子类型

    逗比时刻:

      Python崇尚鸭子类型,

    # list tuple
    # 不崇尚根据继承所得来的相似
    # 我只是自己实现我自己的代码就可以了。
    # 如果两个类刚好相似,并不产生父类的子类的兄弟关系,而是鸭子类型
    # list tuple 这种相似,是自己写代码的时候约束的,而不是通过父类约束的
    # 优点 : 松耦合 每个相似的类之间都没有影响
    # 缺点 : 太随意了,只能靠自觉

    封装

    # 广义上面向对象的封装 :代码的保护,面向对象的思想本身就是一种
    # 只让自己的对象能调用自己类中的方法
    # 狭义上的封装 —— 面向对象的三大特性之一
    # 属性 和 方法都藏起来 不让你看见

    class Person:
        __key = 123       #私有静态属性
        def __init__(self,name,pwd):
            self.name = name
            self.__pwd = pwd      #对象私有属性
        def __get_pwd(self):          #私有方法
            return self.__pwd
        def s(self):                    #正常调用私有方法
            return self.__get_pwd()
    p = Person("xiaoli",123456)
    print(p.__dict__)        #查看对象p的属性值
    print(p._Person__pwd)   #查看对象p的密码  _类名__属性名
    print(Person._Person__key)     #查看Person类的私有静态属性
    print(p.s())  #正常调用

    # 所有的私有 都是在变量的左边加上双下划綫
    # 对象的私有属性
    # 类中的私有方法
    # 类中的静态私有属性
    # 所有的私有的 都不能在类的外部使用

    class Foo:
        __key = '123'       # _Foo__key
    
    class Son(Foo):
        print(Foo.__key)     # _Son__key
    
    # 会用到私有的这个概念de场景
    #1.隐藏起一个属性 不想让类的外部调用
    #2.我想保护这个属性,不想让属性随意被改变
    #3.我想保护这个属性,不被子类继承
    # property
    # 内置装饰器函数 只在面向对象中使用
    
    #属性 查看 修改 删除
    class Person:
        def __init__(self,name):
            self.__name = name
        @property      # 把属性伪装成一个方法 不能传参数
        def name(self):
            return self.__name
        @name.deleter     # 在外部调用同属性一样的方法名来删除属性,不能传参数   与del配合使用
        def name(self):
            del self.__name
        @name.setter        #在外部调用同属性名一样的方法来修改属性值,只可传一个值
        def name(self,new_name):
            self.__name = new_name
    brother2 = Person('二哥')
    brother2.name = 'newName'
    del brother2.name
    print(brother2.name)
    @property
    class Goods:
        __discount = 0.8
        def __init__(self,name,price):
            self.name = name
            self.__price = price
        @property
        def price(self):
            return self.__price * Goods.__discount
        @classmethod   # 把一个方法 变成一个类中的方法,这个方法就直接可以被类调用,不需要依托任何对象
        def change_discount(cls,new_discount):  # 修改折扣
            cls.__discount = new_discount
    apple = Goods('苹果',5)
    print(apple.price)
    Goods.change_discount(0.5)   # Goods.change_discount(Goods)
    print(apple.price)
    # 当这个方法的操作只涉及静态属性的时候 就应该使用classmethod来装饰这个方法
    @classmethod
    class Login:
        def __init__(self,name,password):
            self.name = name
            self.pwd = password
        def login(self):pass
    
        @staticmethod
        def get_usr_pwd():   # 静态方法
            usr = input('用户名 :')
            pwd = input('密码 :')
            Login(usr,pwd)
    
    Login.get_usr_pwd()
    # 在完全面向对象的程序中,
    # 如果一个函数 既和对象没有关系 也和类没有关系 那么就用staticmethod将这个函数变成一个静态方法
    @staticmethod

    # 类方法和静态方法 都是类调用的
    # 对象可以调用类方法和静态方法么? 可以 一般情况下 推荐用类名调用
    # 类方法 有一个默认参数 cls 代表这个类 cls 同对象的self 一样
    # 静态方法 没有默认的参数 就象函数一样

    反射

    class Person:
        key = 123
        def __init__(self,name,sex):
            self.name = name
            self.sex = sex
        def da(self):
            print("打人")
        @classmethod
        def f(cls):
            print("人生")
        @staticmethod
        def login():
            print("hh")
    
    s = getattr(Person,"key")  #通过反射,类名获取静态属性
    print(s)   #   123
    s1 = getattr(Person,"da") #通过反射,类名获取公共方法
    print(s1) #    <function Person.da at 0x000001AB42A73840> 是一个地址
    s1(s) # 打人    #地址加()才能执行这个方法 而必须要传一个参数(因为上面self)
    s2 =getattr(Person,"f")  #  通过反射,类名获取 类方法
    print(s2) # <bound method Person.f of <class '__main__.Person'>>
    s2() # 人生
    s3 = getattr(Person,"login")  #通过反射,类名调用静态方法
    s3() # hh
    
    p = Person("h","nan")
    s4 = getattr(p,"key")   #通过反射 对象名获取静态属性
    print(s4) # 123
    s5 = getattr(p,"da")
    s5() #  打人          #通过反射,对象名获取方法
    
    #s6 = getattr(p,"ky")   # 不论类名 还是 对象名 调用没有值的时候 都是报错
    #print(s6)   # AttributeError: 'Person' object has no attribute 'ky'
    
    if hasattr(p,"ky"): # hasattr 检验是否有这个值,如果有 getattr可以取到,没有则什么都不显示
        s7 = getattr(p,"ky")
        print(s7)   #没有任何显示
    
    if hasattr(Person,"key"):    #   hasattr  和 getattr  是一个组合用
        s8 = getattr(Person,"key")
        print(s8)   #123
    View Code
  • 相关阅读:
    如何搭建ssh服务?
    安利三款提升幸福感的chrome插件
    EF6学习笔记七:代码迁移
    EF6学习笔记六:实体拆分(Entity Spliting)实现TPT、表拆分(Table Spliting)实现TPH
    EF6学习笔记五:继承三策略
    EF6学习笔记四:一对多、多对多、一对一关系配置(Fluent API)
    EF6学习笔记三:全局约定和自定义约定,整理并记下来
    EF6学习笔记二:一些详细配置,开始设计一个稍微能用的数据模型
    EF6学习笔记一:code-first简单创建数据库、表的一些过程
    Spring Cloud微服务实战 打造企业级优惠券系统 2-9 Spring Data JPA
  • 原文地址:https://www.cnblogs.com/bzluren/p/10747110.html
Copyright © 2020-2023  润新知