PythonDay10---面向对象高级编程:

Python之面向对象高级编程

一、使用_slots_

1.如何为实例对象绑定实例方法?

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。

说明:用MethodType()方法将实例函数绑定到对象上。
eg:

from types import MethodType
class Student(object):
    pass
        
def set_age(self, age):
    self.age = age

s = Student()
s.set_age = MethodType(set_age, s)  #(核心语句)第一个参数是要绑定的方法,第二个参数是要绑定的对象,第三个参数是类名(可省略)
s.set_age(30)
print(s.age)

#结果:
30

注意:给一个实例绑定的方法,对另一个实例是不起作用的,另外,用MethodType()函数需要导入模块。

2.如何为类绑定方法?

说明:直接用类名.方法名 = 方法名语句,可以为类绑定方法。
eg:

class Student(object):
    pass
        
def set_age(self, age):
    self.age = age

Student.set_age = set_age		#核心语句
s = Student()
s.set_age(20)
print(s.age)

结果:
20

通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现

3.使用__slots__

但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加nameage属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性

class Student(object):
    
    __slots__ = ('name', 'age')
    
    def __init__(self, name):
        self.name = name
        
s = Student('ZhangSan')
s.age = 18
print(s.age)
s.score = 100
print(s.score)

# 结果:
18
Traceback (most recent call last):
  File "D:\python\temp.py", line 11, in <module>
    s.score = 100
AttributeError: 'Student' object has no attribute 'score'

需要注意两点:
(1)如果设置了__slots__,无论是类的内部也不能设置其以外的属性。
(2) __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的。除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__

二、使用@property装饰器

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改,比如成绩属性score可以赋值200分,这明显不和逻辑。当然我们可以想java一样定义setget方法,但是这样比较繁琐,没有直接用属性这么直接简单。
那么问题来了,有没有既能检查参数,又可以用类似属性这样简单的方式来访问类的变量呢?
对于追求完美的Python程序员来说,这是必须要做到的!而Python内置的@property装饰器就是负责把一个方法变成属性调用的:

class Person(object):

    def __init__(self, name, age):
        self._name = name
        self._age = age

    # 访问器 - getter方法
    @property
    def name(self):
        return self._name

    # 访问器 - getter方法
    @property
    def age(self):
        return self._age

    # 修改器 - setter方法
    @age.setter
    def age(self, age):
        self._age = age

    def play(self):
        if self._age <= 16:
            print('%s正在玩飞行棋.' % self._name)
        else:
            print('%s正在玩斗地主.' % self._name)


def main():
    person = Person('王大锤', 12)
    person.play()
    person.age = 22
    person.play()


if __name__ == '__main__':
    main()

# 结果:
王大锤正在玩飞行棋.
王大锤正在玩斗地主.

把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@age.setter,负责把一个setter方法变成属性赋值。

你可以在想,什么时候属性用公有的、受保护的、私有的?
(1)如果对属性能够任意的赋值,没有审核条件,就设置为公有
(2)如果对属性的赋值有条件限制,就用受保护的
(3)如果该属性只是在类的内部使用,就设置为私有的

由此可见,一般用@property装饰器都是用于受保护类型的属性

三、多重继承

MixIn
在设计类的继承关系时,通常,主线都是单一继承下来的。但是,如果需要“混入”额外的功能,通过多重继承就可以实现,这种多继承设计通常称之为MixIn。
一般我们将其主要继承的类为原名,其他的类加上MixIn后缀,让其够加清洗的明确是使用了多继承,当然,你不加也完全没关系。下面举一个狗多继承的例子:

class Dog(Mammal, RunnableMixIn, CarnivorousMixIn):
    pass

另外说明一下,于Python允许使用多重继承,因此,MixIn就是一种常见的设计。
只允许单一继承的语言(如Java)不能使用MixIn的设计。

四、使用枚举类

当我们需要定义很多常量时,我们需要一个个的设置,很麻烦,这个时候我们可以用枚举类去简化代码:

from enum import Enum

e = Enum('money', ('one', 'five', 'ten'))
print(e, type(e))
for data in e:
    print(data.name, data.value)

# 结果:
<enum 'money'> <class 'enum.EnumMeta'>
one 1
five 2
ten 3

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

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

from enum import Enum,unique

@unique
class myEnum(Enum):
    one = 0
    five = 'five'
    ten = 10

for data in myEnum:
    print(data.name, data.value)
    
# 结果:
one 0
five five
ten 10

@unique装饰器可以帮助我们检查保证没有重复值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ElegantCodingWH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值