• python3 封装之property 多态 绑定方法classmethod 与 非绑定方法 staticmethod


    property 特性

    什么是特性property

    property 是一种特殊的属性,访问它时会执行一段功能(函数),然后返回值

    例如

    BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个属性,更便于理解)
    
    成人的BMI数值:
    过轻:低于18.5
    正常:18.5-23.9
    过重:24-27
    肥胖:28-32
    非常肥胖, 高于32
      体质指数(BMI)=体重(kg)÷身高^2(m)
      EX:70kg÷(1.75×1.75)=22.86
    
    '''
    
    
    
    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    
    
        def bmi(self):
            return self.weight / (self.height * self.height)
    
    egon=People('egon',75,1.80)
    print(egon.bmi())

    #结果为
    23.148148148148145

    #首先需要明确的是 bmi 是算出来的 , 不是一个固定死的值, 也就是说我们必须编写一个功能,
    每次调用该功能,都会立即算出一个值。所以将其做成了一个函数。

    以上虽然方便,但是bmi的值听起来更像一个名词而非动词。  一般名词我们调用一个名词属性就

    就像调用名字那样去调用 egon.bmi 而不是像函数那样去调用不用egon.bmi()

    所以我们还需要将其更近一下。这就用到了 封装中的property.

    它就相当于一个装饰器,我们为bmi这个函数添加装饰器, 将其伪装成一个数据属性

    class People:
         def __init__ (self,name,weight,height):
        
                self.name=name
                self.weight=weight
                self.height=height
    
           @property
            def bmi(self):
            return self.weight / (self.height*self.height)
    
    p1= ('egon',70,1.80)
    print(p1.bmi)
    
    # 结果为
      23.148148148148145

    若是我们想改其中的数值 可以这样更改

    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    
        @property
        def bmi(self):
            return self.weight / (self.height * self.height)
    
    p1=People('egon',75,1.80)
    
    p1.weight=70  # 将其中的体重改为70 , 得到的bmi 值又会更改
    print(p1.bmi)
    
    #打印结果  21.604938271604937

     二  多态:

    多态值得是同一种事物多种形态

    为什么要用多态

    用基类创建一套统一的规则。强制子类去遵循(使用抽象类实现),这样便可以在不用考虑

    对象具体类型的前提下而直接使用对象的下的方法。

    如何使用多态:

    例如猫,狗 猪都是动物  他们都有叫的功能,我们可以在父类中定义好他们的功能,然后不用管子类是猫还是狗还是猪,可以直接调用动物的属性,而不用去考虑他是狗还是猫还是猪。但是在工作中 有可能会是动物是一个人定义的  猫狗猪需要另外一个人来定义, 那么就有可能出现定义猫狗猪的程序员不会按照动物的属性去定义, 那么那样去定义的时候 就需要记住是哪个动物的属性了, 这样无形中就增加的来历复杂度。例如:

    class animal:
        def speak(self)
            pass
    
    class Cat(animal):
         def  jiao(self):
             print('喵喵喵‘)
    
    class Dog(animal):
          def speak(self):
              print('汪汪汪')
    
    class Pig(animal):
            def han(self):
                print('哼哼哼')
    
    #同样都是动物的叫声 要是调用的话 就必须得调用具体动物的属性才可以 :
    c=Cat()
    d=Dog()
    p=Pig()
    
    c.jiao()
    d.speak()
    p.han()
    
    这样就比较麻烦了

    现在我们就可以考虑到多态的好处了,

    接下来说如何用

    再父类的上面加上@ abc  #abc=abstract class, 然后在共同属性函数上 加上这个abc 装饰器

    @abc,abstractmethod 这样子类中的属性就必须要同父类属性一致 ,否则就会报错

    import  abc    #abc=abstract class
    class animal:
    
        @abc.abstractmethod    #加上装饰器 这样子类属性就必须要父类一致,否则无法调用
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
    
        @abc.abstractmethod
        def run(self):
            pass
    
        @abc.abstractmethod
        def bark(self):
            pass
    
    class Cat(animal):
        def eat(self):
            print('cat eat')
    
        def drink(self):
            print('cat drink')
    
        def run(self):
            print('cat run')
    
        def bark(self):
            print('喵喵喵')
    
    class Dog(animal):
        def eat(self):
            print('dog eat')
    
        def drink(self):
            print('dog drink')
    
        def run(self):
            print('dog run')
    
        def bark(self):
            print('汪汪汪')
    
    class Pig(animal):
        def eat(self):
            print('pig eat')
    
        def drink(self):
            print('pig drink')
    
        def run(self):
            print('pig run')
    
        def bark(self):
            print('哼哼哼')
    
    c=Cat()
    d=Dog()
    p=Pig()
    
    c.eat()
    c.bark()
    c.run()
    c.drink()

    三  鸭子类型

    python 崇尚鸭子类型, 即‘如果看起来像, 叫声像, 而且走起路来像鸭子, 那么它就是鸭子’

    python程序员通常根据这种行为来编写程序, 例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但是与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度。

    class Foo:
        def  f1(self):
            print('from foo.f1')
    
         def f2(self):
            print('from foo.f2')
    
    class Bar:
        
          def f1(self):
             print('feom bar.f1')
        
    
           def f2(self):
        
                print('from bar.f2')
    
    obj1 =Foo()
    obj2 =Bar()
    
    obj1.f1()
    obj1.f2()
    
    obj2.f1()
    obj2.f2()

    这就是鸭子类型

    四  绑定方法 classmethod  与 非绑定方法 staticmethod

    类中定义的函数分为两大类:

    一:绑定方法(绑定给谁, 谁来调用就自动将它本身当做第一个参数传入):

    绑定对象的方法特殊之处:

         应该由对象来调用 ,对象来调用,会自动将对象当做第一个参数传入

    绑定到类的方法:用classmethod 装饰器装饰的方法。

    classmethod 是给类用的,即绑定到类, 类在使用是会将本身当做参数传给类方法的第一个参数,(即便是对象来调用也会将类当做第一个参数传入,)python为我们内置了函数classmethod 来把类中的函数定义成类方法。

    import setting   #导入模块里的
    class People:
        def __init__(self,name,age):
            self.name=name
            self.age=age
    
        def tell(self):
            print('%s:%s'%(self.name,self.age))
    
        @classmethod    #给类使用
        def from_conf(cls):
            return cls(setting.NAME,setting.AGE)
    
    p=People.from_conf()
    p.tell()

    非绑定方法  staticmethod  就是一个普通函数,

    特性 即不跟类绑定, 也不跟对象绑定, 这意味着谁都能用,

    谁来用都是一个普通函数, 也就是说没有自动传值的特性了

    import settings
    import hashlib
    import time
    
    class People:
        def __init__(self,name,age):
            self.uid=self.create_id()
            self.name=name
            self.age=age
    
        def tell(self):
            print('%s: %s:%s' %(self.uid,self.name,self.age))
    
        @classmethod
        def from_conf(cls):
            return cls(settings.NAME,settings.AGE)
    
        @staticmethod
        def create_id():
            m=hashlib.md5()
            m.update(str(time.clock()).encode('utf-8'))
            return m.hexdigest()
    
    obj=People('egon',18)
    # print(obj.uid,obj.name,obj.age)
    # obj.tell()
    
    # print(obj.create_id)
    # print(People.create_id)
    
    print(obj.create_id())
    print(People.create_id())
  • 相关阅读:
    BZOJ1146:[CTSC2008]网络管理
    AtCoder Grand Contest 004 C:AND Grid
    BZOJ3295:[CQOI2011]动态逆序对
    AtCoder Regular Contest 070F:Honest Or Unkind
    BZOJ3110:[ZJOI2013]K大数查询
    BZOJ3196:二逼平衡树
    浅谈splay
    BZOJ3938:Robot
    浅谈标记永久化
    AtCoder Regular Contest 068E:Snuke Line
  • 原文地址:https://www.cnblogs.com/lx3822/p/8857078.html
Copyright © 2020-2023  润新知