__ getatter __ 魔法方法
-
首先会在对象的实例属性中寻找,找不到执行第二步
-
来到对象所在类中查找类属性,如果还找不到执行第三步
-
来到对象的继承链上寻找,如果还找不到执行第四步
-
调用
obj.__getattr__
方法,如果用户没有定义或者还是找不到,抛出AttributeError
异常,属性查找失败!
# -*- coding: utf-8 -*-
# @Author: Small-J
# @Date : 2020/12/18
# 该文件对应着视频-__getattr__和__getattribute__魔法函数
"""
总结如下:
__getatter__:该魔术方法什么时候执行呢,是当一个类中没有该属性的时候调用该魔法方法执行
"""
from datetime import date
class User(object):
def __init__(self, name, birthday):
self.name = name
self.birthday = birthday
def __getattr__(self, item):
# print('attr not find')
return None
if __name__ == '__main__':
user = User('small-j', date(year=2020, month=12, day=18))
print(user.name) # small-j
# 当如果打印一个不存在的值的时候
# 字面意思:没有该属性值
# print(user.age) # AttributeError: 'User' object has no attribute 'age'
#
print(user.age)
属性描述符
__set__
: 该魔法方法是设置属性时生效__get__
: 该魔法方法是在读取属性值时生效__delete__
: 该魔法方法是进行对应删除时调用
# -*- coding: utf-8 -*-
# @Author: Small-J
# @Date : 2020/12/18
# 该文件对应着视频-属性描述符
"""
总结如下:
__set__:该魔术方法的作用:就是在设置值的时候,会进入这个方法,但是这个方法只是设置的时候进入的,
instance : 该参数是object对象
value: 就是我们想要的值
__get__ : 该魔法方法作用:就是在读取属性的时候会触发该魔法方法
"""
class IntField(object):
def __get__(self, instance, owner): # 在属性获取的时候会进入这个方法
return self.age
def __set__(self, instance, value): # 在属性设置的时候会进入这个方法
if not isinstance(value, int):
raise ValueError
# 因为设置的时候我们会进入这个方法,所以我们得在这使用值,在通过调用的形式,让__get__来读取出来
self.age = value
def __getattr__(self, item): # 当没有属性的时候将会报错,我们要捕获这个异常,让他返回None
return None
class User(IntField):
age = IntField()
user = User()
user.age = 20
print(user.age)
print(user.aaa)
Python-迭代器
- 迭代器和可迭代对象是两个不同的概念,可迭代对象不一定是迭代器。如
list
- 什么是可迭代对象:可迭代对象是含有
__iter__
这个魔法方法,这个魔法方法就是用来定义可迭代对象 - 什么是迭代器:迭代器是含有
__next__
、__iter__
这两个魔法方法 - 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 为什么list不是迭代器,因为list含有
__iter__
这个魔法方法,但是并不含有__next__
该方法,那怎么把list变成迭代器呢?通过iter
这个方法
# -*- coding: utf-8 -*-
# @Author: Small-J
# @Date : 2020/12/19
# 该文件对应着视频-python迭代器
"""
总结如下:
可迭代对象和迭代器是不同的内容
什么是可迭代对象:可迭代对象是内部含有__iter__这个魔法方法的是可迭代对象,
为什么list不是迭代器,因为内部没有__next__这个魔术方法,但内部有__iter__这个魔法方法
什么是迭代器:迭代器是通过可以通过next来获取到下一位的是可迭代器
可迭代对象不一定是迭代器
"""
from collections import Iterable, Iterator
# 可迭代对象Iterable,定义__iter__
# True : 说明list也是一个可迭代的对象
# print(isinstance(list(), Iterable))
# False : 说明list不是迭代器,
# print(isinstance(list(), Iterator))
li = [1, 2, 3, 4]
# 从是一个列表转换成一个列表迭代器
# print(iter(li)) # <list_iterator object at 0x7fda40194390>
li = iter(li)
# 当想从一个迭代器中获取值的话只能next
# print(next(li))
# print(next(li))
# print(next(li))
# print(next(li))
# print(next(li)) # 当超过取值时会报出StopIteration这么一个错误
# 当如果数据特别多时,我们需要使用另外一种方法来解决现状
while True:
try:
print(next(li))
except StopIteration:
break
Python-生成器
- 在Python中没有元祖推导式?->这是为什么?
- 因为元祖最终的效果是属于生成器
- 一般生成器对象可以使用
next
方法来获取数据 - 当使用
yield
关键字的时候,如果数据没有了则不会报错,因为在内部yield
做了一定的处理 - 如果不使用yield的关键字,当next无的时候将会报错
- 跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器
- 调用一个生成器函数,返回的是一个迭代器对象。
# -*- coding: utf-8 -*-
# @Author: Small-J
# @Date : 2020/12/20
# 该文件对应着视频-Python生成器
"""
总结如下:
在Python中没有元祖推导式,元祖是生成器
一般生成器对象可以使用next方法来获取数据
当使用yield关键字的时候,如果数据没有了则不会报错,因为在内部yield做了一定的处理
如果不使用yield的关键字,当next无的时候将会报错
"""
# 我们Python中有列表推导式,有字典推导式,但是就是没有元祖推导式,这是为什么,原因如下
a = [i for i in range(1, 10)] # type: # list
b = (i for i in range(1, 10)) # type: # generator
d = {'name': 'Small-J', 'a': 10, 'b': 20}
c = {value: key for key, value in d.items()}
# 斐波那契数列
# 1,1,2,3,5,8,13
def data(n):
a = 0
b = 1
count = 0
while True:
if count > n:
return
a, b = b, a+b
count += 1
print(a)
#
def demo():
a = [i for i in range(3)]
yield a
# 打印的结果是为生成器所使用
# print(demo()) # <generator object demo at 0x7fc8902a6550>
# 当使用yield关键字的时候,如果数据没有了则不会报错,因为在内部yield做了一定的处理
# 如果不使用yield的关键字,当next无的时候将会报错
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
# print(next(demo()))
type自定义元类编程
- 创建类的方法有很多,除了可以通过
class
关键字来创建之外,也可以通过type
来创建,type
既可以创建类也可以查询数据类型 type(name, bases, dict) -> a new type
- name: 创建类的名字
- bases:继承的类,父类,以元祖的形式
- dict: 以字典的形式,接受各种魔法方法和相对应的类方法,当创建类方法时,必须要加self,否则无效
# 当我想以元类编程的形式创建出一个类方法的话,可以如下操作
# 要遵守元类编程和创建类方法的写法,需要加self
def info(self):
return self.age
class BaseData(object):
def demo(self):
return 'Small-J'
def __init__(self):
self.height = 180
self.width = 100
def __getattr__(self, name):
return None
# 对应的这是一个类
# "age": 18 ->相当于类方法
User = type('User', (BaseData, ), {"age": 18, 'info': info, '__init__': __init__, '__getattr__': __getattr__}) # <class '__main__.User'>
# 实例化这个类
user = User()
print(user.age)
print(user.info()) # 相当于调用方法
# print(user.age) # 18
# 通过实例化方式来调用父类中的方法
print(user.demo()) # 也是可以调用的
# 当定义了魔法方法也是可以通过直接调用的
# init魔法方法也可以被调用
print(user.height)
# 当没有该属性时也会触发__getattr__这个魔法方法来进行,注意:必须要加上self,默认是没有加上self的
print(user.dddd)