• 封装之property,多态,鸭子类型,classmethod与staticmethod


    一、封装之Property

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

    '''
    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
    
        ## @property  
        def bmi(self):
            return self.weight / (self.height * self.height)
    
    egon=People('egon',75,1.80)    #调用类产生一个对象
    
    egon.bmi=egon.weight / (egon.height * egon.height)
    print(egon.bmi)

    property方法

    class People:
        def __init__(self,name,weight,height):
            self.name=name
            self.weight=weight
            self.height=height
    
        @property          #把一个函数伪装成数据属性,对象调用函数属性不需要加(),@property ,不加括号调用打印得到的是绑定方法的内存地址
        def bmi(self):
            return self.weight / (self.height * self.height)
    
    #方法一调用(@property注释掉,1、调用类产生对象,2、对象.函数属性名,3、然后打印即可)
    # egon=People('egon',75,1.80)
    # egon.bmi=egon.weight / (egon.height * egon.height)        #没有此行打印的是一个绑定方法的内存地址
    # print(egon.bmi)             # =>>>23.148148148148145
    #
    # yl=People('yangli',85,1.74)
    # yl.bmi=yl.weight / (yl.height * yl.height)
    # print(yl.bmi)
    
    # 首先需要明确。bmi是算出来的,不是一个固定死的值,也就说我们必须编写一个功能,每次调用该功能
    #都会立即计算一个值
    egon=People('egon',75,1.80)
    # yl=People('yangli',85,1.74)
    
    
    # 但很明显人的bmi值听起来更像一个名词而非动词
    # print(egon.bmi())               #=>>>>>23.148148148148145
    # print(yl.bmi())                #=>>>>28.075042938300964
    
    
    # 于是我们需要为bmi这个函数添加装饰器,将其伪装成一个数据属性
    egon.weight=70
    print(egon.bmi) #21.604938271604937,调用egon.bmi本质就是触发函数bmi的执行,从而拿到其返回值
    # print(yl.bmi)
    

      

    二、多态

    1、什么是多态?

    多态指的是同一种事物的多种形态

    2、为什么使用多态?

    用基类创建一套统一的规则,强制子类去遵循(使用抽象类去实现),这样便可以在不考虑对象具体类型的前提下,而直接使用对象下的方法

    3、如何用多态?

    # class Animal:            #基类创建一套统一的规则,猫,狗,猪都属于动物,都具有动物的属性,吃、喝、跑、叫
    #     def eat(self):        #在子类中引用相同函数属性的名字,可以不考虑对象的类型,直接使用对象下的方法
    #         pass
    #
    #     def drink(self):
    #         pass
    #
    #     def run(self):
    #         pass
    #
    #     def bark(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.eat()
    # # d.eat()
    # # p.eat()
    # #
    # # c.drink()
    # # d.drink()
    # # p.drink()
    #
    #
    # # d.bark()
    # # p.bark()
    # # c.bark()
    #
    # d.speak()
    # c.jiao()
    # p.han()
    View Code

    引入abc模块,通过装饰器来装饰,使得同一类事物,派生必须在我定义属性之内

    import abc #abstract class             #引入抽象类
    class Animal(metaclass=abc.ABCMeta):           #目的使得派生必须在我定义的属性之内
        @abc.abstractmethod
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
    
        @abc.abstractmethod
        def run(self):
            pass
    
        @abc.abstractmethod
        def bark(self):
            pass
    
    # obj=Animal() # 抽象基类本身不能被实例化
    
    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.bark()
    # d.bark()
    # p.bark()
    
    
    # def BARK(animal):
    #     animal.bark()
    #
    #
    # BARK(c)
    # BARK(d)
    # BARK(p)
    
    
    #python中一切皆对象
    s='hello'
    l=[1,2,3]
    t=(4,5,6)
    
    s.__len__()
    l.__len__()
    t.__len__()
    
    
    # def LEN(obj):
    #     return obj.__len__()
    #
    # print(LEN(s))
    # print(LEN(l))
    # print(LEN(t))
    print(len(l))
    print(len(s))
    print(len(t))

    三、鸭子类型

    鸭子类型就是看起来像,而且走起路来和叫声也像,那么他就是鸭子

    #创建一个外观与行为像,但与它无任何关系的全新对象
    class Foo:
        def f1(self):
            print('from foo.f1')
    
        def f2(self):
            print('from foo.f2')
    
    class Bar:
        def f1(self):
            print('from bar.f1')
    
        def f2(self):
            print('from bar.f2')
    
    
    obj1=Foo()
    obj2=Bar()
    
    
    obj1.f1()
    obj1.f2()
    
    obj2.f1()
    obj2.f2()
    
    
    #三者都具有读写的功能,但是并没有直接的关系
    
    class Disk:
        def read(self):
            print('disk read')
    
        def write(self):
            print('disk write')
    
    
    class Txt:
        def read(self):
            print('txt read')
    
        def write(self):
            print('txt write')
    
    
    class Process:
        def read(self):
            print('process read')
    
        def write(self):
            print('process write')
    
    
    obj1=Disk()
    obj2=Txt()
    obj3=Process()
    
    
    obj1.read()
    obj2.read()
    obj3.read()
    View Code

      

    四、绑定方法

    '''
    1 绑定方法:
    在类内部定义的函数,默认就是给对象来用,而且是绑定给对象用的,称为对象的绑定方法即obj.name
    绑定对象的方法特殊之处:
    应该由对象来调用,对象来调用,会自动将对象当作第一个参数传入

    绑定到类的方法特殊之处:
    应该由类来调用,类来调用,会自动将类当作第一个参数传入
    在类内定义的函数是类的函数属性,是给对象用的,是对象的绑定方法
    '''
    classmethod是类用的,是绑定到类的,类在调用时会将类本身当做参数传给类方法的第一个参数(即便是对象调用,也会将类当做第一个参数传入)
    import settings                # settings.py中内容:     NAME='lxx' AGE=30
    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(settings.NAME,settings.AGE)
    
    
    # p=People('egon',19)
    # p.tell()
    
    # p1=People(settings.NAME,settings.AGE)
    # p1.tell()
    
    # p2=People(settings.Name,settings.AGE)
    
    
    # p3=People('alex',74)
    # p3.tell()
    
    # print(People.from_conf)
    # p4=People.from_conf(People)
    # print(People.from_conf)
    # p4=People.from_conf()
    # p4.tell()
    View Code

    2、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())
    

      

     



  • 相关阅读:
    前端开发-学习资料库
    前端数据校验从建模开始
    让 Markdown 中的代码可以实时运行
    小而美的 React Form 组件
    React 实现一个漂亮的 Table
    RSuite 一个基于 React.js 的 Web 组件库
    管理系统的前端解决方案:Pagurian V1.3发布
    selenium java 自动化测试 基于火狐浏览器/谷歌浏览器
    java从ldap中导出数据到ldif文件中
    根据官方文档搭建springcloud之eureka
  • 原文地址:https://www.cnblogs.com/sui776265233/p/8856538.html
Copyright © 2020-2023  润新知