# -*- encoding: utf-8 -*-
import os
'''
第35条: 用元类来注解类的属性
关键:
1 元类
作用:在类定义好但是还没有使用的时候,提前修改或注解类的属性,
该写法通常会与描述符搭配起来,使这些属性可以了解自己在外围类的使用方式
应用场景:
定义某个类,表示客户数据库中的某一行。还希望该类的相关属性与数据库表
的没一列之间,建立对应关系
2 描述符
描述符类: 可以提供__get__和__set__方法
原理:
exam.writingGrade = 40
会被转换为
Exam.__dict__['writingGrade'].__set__(exam, 40)
获取属性会被转换为
Exam.__dict__['writingGrade'].__get__(exam, Exam)
之所以存在上述转换: 是因为object类的__getattribute__方法
类实例没有某个属性 ---> 在类中查找同名属性(
类属性,如果实现了__get__和__set__方法,则认为该对象遵循描述符协议)
3 总结
元类可以在类完全定义好之前,修改该类的属性;
描述符与元类组合后,可以对行为作出修饰,不使用weakref就避免内存泄露
参考:
Effectiv Python 编写高质量Python代码的59个有效方法
'''
'''
描述符类: 把属性与列名联系起来。
列的名称已经保存到了Field描述符中。
'''
class Field2(object):
def __init__(self, name):
self.name = name
self.internalName = "_" + self.name
def __get__(self, instance, instance_type):
if instance is None:
return self
return getattr(instance, self.internalName, '')
def __set__(self, instance, value):
setattr(instance, self.internalName, value)
class Customer(object):
# Class attributes
first_name = Field2('first_name')
last_name = Field2('last_name')
prefix = Field2('prefix')
suffix = Field2('suffix')
def useCustomer2():
customer = Customer()
print "Before: {value}, {mydict}".format(
value=repr(customer.first_name),
mydict=customer.__dict__
)
customer.first_name = 'Chen'
print "After: {value}, {mydict}".format(
value=repr(customer.first_name),
mydict=customer.__dict__
)
class Field(object):
def __init__(self):
# 下面的属性已经被元类设置了
self.name = None
self.internalName = None
def __get__(self, instance, instance_type):
if instance is None:
return self
return getattr(instance, self.internalName, '')
def __set__(self, instance, value):
return setattr(instance, self.internalName, value)
class Meta(type):
def __new__(meta, name, bases, class_dict):
for key, value in class_dict.items():
if isinstance(value, Field):
value.name = key
value.internalName = "_" + key
cls = type.__new__(meta, name, bases, class_dict)
return cls
class DatabaseRow(object):
__metaclass__ = Meta
class BetterCustomer(DatabaseRow):
first_name = Field()
last_name = Field()
prefix = Field()
suffix = Field()
def useCustomer():
customer = Customer()
print "Before: {value}, {mydict}".format(
value=repr(customer.first_name),
mydict=customer.__dict__
)
customer.first_name = 'Chen'
print "After: {value}, {mydict}".format(
value=repr(customer.first_name),
mydict=customer.__dict__
)
def process():
useCustomer()
if __name__ == "__main__":
process()
Effective Python 读书笔记: 第35条: 用元类来注解类的属性
猜你喜欢
转载自blog.csdn.net/qingyuanluofeng/article/details/88940865
今日推荐
周排行