from datetime import date, datetime
class User:
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
def get_age(self):
return datetime.now().year - self.birthday.year
@property
def age(self): # @property会将方法名转变为 属性描述符
return datetime.now().year - self.birthday.year
if __name__ == '__main__':
user = User('bob', date(year=1980, month=1, day=1))
print(user.get_age())
print(user.age) # 不用加括号, 效果与方法get_age()一样
也可以动态设置:
class User:
def __init__(self):
self._sex = 0
@property
def sex(self):
return self._sex
@sex.setter
def sex(self, value):
self._sex = value
if __name__ == '__main__':
user = User()
print(user.sex) # 0
user.sex = 1
print(user.sex) # 1
class User:
def __getattr__(self, item):
return 'not found',item
user = User()
print(user.name) # not fount name
利用__getattr__完成更复杂的逻辑 :
class User:
def __init__(self, name, **info): # 用户的详细信息将传入字典info中
self.name = name
self.info = info
def __getattr__(self, item): # 当某些属性找不到时
return self.info[item] # 直接获取字典中的值
if __name__ == '__main__':
user = user('bob', age=19)
print(user.age) # 19
class User:
def __init__(self, name):
self.name = name
def __getattribute__(self, item): # 不论获取什么属性都会先通过这个魔法属性
return 'I love python' # 全部返回'I love python', 不论是否有这个属性
user = User('Ami')
print(user.name) # 'I love python'
print(user.age) # 'I love python'
一个类实现任何一个__get__ , __set__ , __delete__ 魔法方法, 都可以称为属性描述符
class IntField:
def __get__(self, instance, owner): # 获取值时调用, 其中的参数instance是 User类的实例
pass # 参数owner是 User类
def __set__(self, instance, value): # 设置值时调用
pass
def __delete__(self, instance): # 删除值时调用
pass
class User:
age = IntField()
# def __init__(self, age=None): # 如果放到初始化函数中, 属性描述符并不会被调用
# self.age = age
例子: 将类User的age属性强制规定为数字类型(虽然这个要求可以用很简单的代码完成, 但是当大量的属性都要依照这个要求时, 就会产生大量的代码冗余, 通过属性描述符
, 我们可以将其都赋为属性描述符的实例即可)
import number
class IntField:
def __set__(self, instance, value):
if not isinstance(value, number.Integral): # 如果不是Integral类型, 抛出异常
raise ValueError('Integral is needed')
self.value = value # 如果符合要求, 将其储存在属性描述符的实例中 !(而不是存储在instance中)
def __get__(self, instance, owner):
return self.value
class User:
age = IntField()
if __name__ == '__main__':
user = User()
user.age = 20
print(user.age)
class User:
def __init__(self, age):
self.age = age
def __getattribute__(self, item):
pass
def __getattr__(self, item)
pass
user = User(18)
如果user是某个类的实例,那么user.age(以及等价的getattr(user,’age’))
首先调用__getattribute__。如果类定义了__getattr__方法,
那么在__getattribute__抛出 AttributeError 的时候就会调用到__getattr__,
而对于描述符(__get__)的调用,则是发生在__getattribute__内部的。
user = User(), 那么user.age 顺序如下:
(1)如果“age”是出现在 类 User或其基类的__dict__中, 且age是data descriptor, 那么调用其__get__方法, 否则
(2)如果“age”出现在 实例 user的__dict__中, 那么直接返回 obj.__dict__[‘age’], 否则
(3)如果“age”出现在User或其基类的__dict__中
(3.1)如果age是non-data descriptor,那么调用其__get__方法, 否则
(3.2)返回 __dict__[‘age’]
(4)如果User有__getattr__方法,调用__getattr__方法,否则
(5)抛出AttributeError
type动态创建类语法 :
User = type(object_or_name, base, dict) # object_or_name: 名称, base: 基类(元组), dict: 属性
利用这种语法添加方法:
def say(self): # 一定要有一个参数
return 'hello'
# 创建User类
User = type('User', (), {
'name':'LiLei', 'say':say}) # 其中base基类没有就写一个空元组
疑问: 通过type创建出来的类, {}中的属性是类属性还是实例属性?
u = User()
u.age = 18
print(User.name)
print(u.name)
print(u.__dict__) # {'age': 18}
print(User.__dict__) # {'name': 'LiLei', 'say': ...... }
__dict__ 存储了该对象的一些属性, 由此看来, 利用type创建类是, {}中添加的属性是类属性(因为这本来就是创建一个类…)
如果有基类要继承 :
class BaseClass:
def run(self):
print('running...')
User = ('User', (BaseClass, ), {
}) # 注意: 第二个参数一定是一个元组
元类的定义:
元类就是创建类的类
对象 <-- class <-- type
对象是类创建的(在python中类也是对象), 类是type创建的class A:
pass
a = A()
print(type(A)) # 一个类的type是 type
print(type(a)) # 一个对象的type是 类
print(type(type)) #
class MetaClass(type): # 继承了type, 这个类就是元类
pass
class User(metaclass=MetaClass): # 注意: 通过mateclass指定参数, 控制User类的实例化过程
pass
Python类的实例化过程: 会首先去
本类或基类或模块 中寻找 metaclass, 如果都没有找到, 就会去利用type去创建类对象. metaclass的优先级特别高
如果重写metaclass中的__new__, 将它生成对象的过程委托给它的父类(type) :
class MetaClass01(type):
def __new__(cls, *args, **kwargs):
print('MetaClass01.__new__')
m_obj = super().__new__(cls, *args, **kwargs)
print('m_obj', m_obj) # m_obj 产生了一个对象
print('type(m_obj)', type(m_obj)) # type(m_obj)
print('type(type(m_obj))', type(type(m_obj))) # type(type(m_obj))
return m_obj
class User(metaclass=MetaClass01):
# def __new__(cls, *args, **kwargs): 这里不要再写__new__, 会报错
# return super.__new__(cls)
pass
u = User()
print('u ', u)
元数据:
关于数据的数据, 描述数据属性的信息
中间件:
是介于应用软件和系统软件之间的一类软件, 提供资源共享, 功能共享的目的
持久层:
负责数据库的访问
实际应用在关系型数据库和业务实体对象之间做一个映射, 这样, 我们在具体的操作业务对象的时候, 就不需要再去和SQL语句打交道, 只要像平时操作对象一样操作它就可以了.