Python day7 面向对象高级编程 (2)

2024-08-01 21:02:02 浏览数 (2)

数据封装、继承和多态只是面向对象程序设计中最基础的3个概

使用slots和@property

slots限制实例的绑定属性

想要限制实例的属性,例如只允许对Student实例添加name和age属性:Python允许在定义class的时候,定义一个特殊的slots变量,来限制该class实例能添加的属性

代码语言:python代码运行次数:0复制
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

就会发现类的实例属性score属性不能绑定了,slots定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

@property

能检查参数,又可以用类似属性这样简单的方式来访问类的变量

代码语言:python代码运行次数:0复制
class Student(object):
    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self, value):
        self._birth = value

    @property
    def age(self):
        return 2015 - self._birth

上面的birth是可读写属性,而age就是一个只读属性,因为age可以根据birth和当前时间计算出来

代码语言:python代码运行次数:0复制
#要特别注意:属性的方法名不要和实例变量重名
#错误案例
class Student(object):
    # 方法名称和实例变量均为birth:
    @property
    def birth(self):
        return self.birth

多重继承

代码语言:python代码运行次数:0复制
class Dog(Mammal, Runnable): #同时获得多个父类的所有功能
    pass

这样额外的功能加入设计也称为MixIn,如Python自带了TCPServer和UDPServer这两类网络服务,而要同时服务多个用户就必须使用多进程或多线程模型,这两种模型由ForkingMixIn和ThreadingMixIn提供。

`

定制类

返回字符

这样打印出来的实例,不但好看,而且容易看出实例内部重要的数据

代码语言:python代码运行次数:0复制
class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self): 
        return 'Student object (name=%s)' % self.name
    __repr__ = __str__

 #__str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串

迭代返回

代码语言:python代码运行次数:0复制
class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a   self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration()
        return self.a # 返回下一个值


>>> for n in Fib():
...     print(n)
...
1
1
2
3
5
...
46368
75025

元素处理

getitem/setitem()/delitem()

像list那样按照下标取出元素,需要实现getitem()方法

代码语言:python代码运行次数:0复制
class Fib(object):
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a   b
        return a

属性获取

要避免这个错误,除了可以加上一个score属性外,Python还有另一个机制,那就是写一个getattr()方法,动态返回一个属性

只有在没有找到属性的情况下,才调用getattr,已有的属性,比如name,不会在getattr中查找

完全动态调用的特性非常灵活

调用实例方法

调用实例方法时,我们用instance.method()来调用,也可以直接对实例进行调用

callable()函数,我们就可以判断一个对象是否是“可调用”对象

枚举类

Enum可以使得每个常量都是class的一个唯一实例

代码语言:python代码运行次数:0复制
# 1
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)
  • Enum的第一个参数是枚举的类名,第二个参数是一个包含枚举成员名称的元组
  • 遍历Month枚举类中的所有成员。枚举成员和它们的名称都存储在特殊的members属性中,这是一个字典;Month.members.items()会返回一个包含(成员名称, 成员)对的迭代器
  • 这行代码在循环中打印每个成员的名称和值,member.value是自动分配给枚举成员的一个唯一值,默认从1开始递增

输出结果为:

Jan => Month.Jan , 1 Feb => Month.Feb , 2

Mar => Month.Mar , 3 Apr => Month.Apr , 4

May => Month.May , 5 Jun => Month.Jun , 6

Jul => Month.Jul , 7 Aug => Month.Aug , 8

Sep => Month.Sep , 9 Oct => Month.Oct , 10

Nov => Month.Nov , 11 Dec => Month.Dec , 12

也可以写成

代码语言:python代码运行次数:0复制
from enum import Enum, unique
@unique
class Weekday(Enum):
    Sun = 0 # Sun的value被设定为0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6

元类(后面再来补充)

type()动态创建类

type()函数可以查看一个类型或变量的类型,Hello是一个class,它的类型就是type,而h是一个实例,它的类型就是class Hello

metaclass控制类的创建行为

代码语言:python代码运行次数:0复制
# metaclass是类的模板,所以必须从`type`类型派生:
class ListMetaclass(type):
    def __new__(cls, name, bases, attrs):
        attrs['add'] = lambda self, value: self.append(value)
        return type.__new__(cls, name, bases, attrs)

ORM

基类

0 人点赞