Python(六)


一、使用__slots__限制某个类的实例的属性

  1. 给类的实例绑定属性和方法

    class Student(object):
        pass
    s = Student()
    s1 = Student() 
    s.name = 'Michael' # 动态绑定属性
    print(s.name)
    
    def set_age(self, age):
        self.age = age
    
    from types import MethodType
    s.set_age = MethodType(set_age, s) # 给实例绑定一个方法,只对该实例起作用
    s.set_age(23)
    # s1.set_age(20) #实例s1没有绑定方法
  2. 给所有实例都绑定方法

    # 给所有实例都绑定方法
    def set_score(self, score):
        self.score = score
        
    Student.set_score = set_score # 给class类绑定方法
    s1.set_score(99)
    s.set_score(98)
  3. 使用__slots__限制实例的属性

    class Student(object):
        __slots__ = ('name','age') # 用tuple定义允许绑定的属性名称
        
    s = Student()
    s.name = 'GuLuyu'
    s.age = 23
    s.score = 99.9 #AttributeError: 'Student' object has no attribute 'score'
  4. 使用__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的,除非在子类中也定义__slots__,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__

二、使用@property

  1. 对属性的限制

    class Student(object):
        def get_score(self):
            return self.score
        def set_score(self,value):
            if not isinstance(value, int):
                raise ValueError('must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('must between 0~100')
            self.score = value
    s = Student()
    s.set_score(100)
    s.get_score()
    s.set_score(-5) 
  2. 可以用Python内置的@property装饰器把一个方法变成属性调用。把一个getter方法变成属性,只需要加上@property就可以,此时,@property本身又创建了另一个装饰器@score.setter,把一个setter方法变成属性赋值。

    class Student(object):
        
        @property    
        def score(self):
            return self._score
        # 属性的方法名不要跟实例变量名重名score\_score
        @score.setter
        def score(self, value):
            if not isinstance(value, int):
                raise ValueError('must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('must between 0~100')
            self._score = value
    
    s = Student()
    s.score = 96
    print(s.score)

三、多重继承

  1. 通过多重继承,一个子类就可以同时获得多个父类的所有功能。

    class Runnable(object):
        def run(self):
            print('Running...')
    
    class Flyable(object):
        def fly(self):
            print('Flying...')
            
    class Animal(object):
        pass
    
    class Mammal(Animal):
        pass
    
    class Bird(Animal):
        pass
    
    class Dog(Mammal, Runnable):
        pass
    
    class Bat(Mammal, Flyable): # 蝙蝠
        pass
    
    class Parrot(Bird, Flyable): # 鸵鸟
        pass
    
    class Ostrich(Bird, Runnable): # 鹦鹉
        pass

    类层次设计

    image-20230505180215465
  2. Mixln即Mix-in,常被译为“混入”,是一种编程模式,在Python等面向对象语言中,通常它是实现了某种功能单元的类,用于被其他子类继承,将功能组合到子类中。利用Python的多重继承,子类可以继承不同功能的 Mixin类,按需动态组合使用。当多个类都实现了同一种功能时,这时应该考虑将该功能抽离成Mixin类。

  3. 上例中,为了更好地看出继承关系,可以把Runnable和Flyable改为RunnableMixIn和FlyableMixIn。

  4. 只允许单一继承的语言(如Java)不能使用MixIn的设计。

四、枚举类

  1. 枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能:

    from enum import Enum
    Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
    for name, member in Month.__members__.items():
        print(name, '=>', member, ',', member.value)        

    value属性则是自动赋给成员的int常量,默认从1开始计数

  2. 如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:

    from enum import Enum, unique
    @unique #@unique装饰器可以帮助我们检查保证没有重复值
    class Weekday(Enum):
        Sun = 0 # Sun的value被设定为0
        Mon = 1
        Tue = 2
        Wed = 3
        Thu = 4
        Fri = 5
        Sat = 6
    print(Weekday.Mon)
    print(Weekday.Tue.value)

    既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。

五、元类

  1. type()函数既可以返回一个对象的类型,又可以创建出新的类型,比如,我们可以通过type()函数创建出Hello类,而无需通过class Hello(object)...的定义:

    def fn(self, name='world'): # 先定义函数
        print('Hello, %s.' % name)
    Hello = type('Hello', (object,), dict(hello=fn)) # 创建Hello class
    h = Hello() # Hello, world.
    h.hello()
    print(type(Hello))

    要创建一个class对象,type()函数依次传入3个参数:

    • class的名称;
    • 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;
    • class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。
  2. metaclass,直译为元类,简单的解释就是:

    当我们定义了类以后,就可以根据这个类创建出实例,所以:先定义类,然后创建实例。

    真叫人头大


文章作者: nusqx
文章链接: https://nusqx.top
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 nusqx !
评论
  目录