通常可以通过点(.)操作符的形式去访问对象的属性,关于属性的访问,也有相应的魔法方法来管理,
属性相关的魔法方法
魔法方法 | 含义 |
__getattr__(self,name) | 定义当用户试图获取一个不存在的属性的行为 |
__getattribute__(self,name) | 定义当该类的属性被访问时的行为 |
__setattr__(self,name,value) | 定义当一个属性被设置时 |
__delattr__(self,name) | 定义一个属性被删除时 |
例子
class C:
def __getattribute__(self,name):#当该类的属性被访问的行为
print('getattribute')
return super().__getattribute__(name)
def __setattr__(self,name,value):#当一个属性被设置时
print('setattr')
super().__setattr__(name,value)
def __delattr__(self,value):#当一个属性被删除
print('delattr')
super().__delattr__(name)
def __getattr__(self,name):#当用户获取一个不存在的上述属性
print('getattr')
运行后
>>> c = C()>>> c.xgetattributegetattr>>> c.x = 1setattr>>> c.xgetattribute1>>> del c.xdelattr
上面的几个魔法方法可能会造成死循环
看例子
要求;写一个矩形类(Rectangle),默认有宽和高两个属性,如果为一个叫做square的属性赋值,那么说明是个正方形,值就是正方形的边长,此时宽高都应等于边长
class Rectangle: def __init__(self,width = 0,height = 0): self.width = width self.height = height def __setattr__(self,name,value): if name == 'square': self.width = value self.height = height else: self.name = value def getArea(self): return self.width * self.height
不妨粘在电脑里运行一下
分析原因,其实就是调用__init__时,不断地去触发__setattr__方法,造成了死循环
更改
class Rectangle:
def __init__(self,width = 0,height = 0):
self.width = width
self.height = height
def __setattr__(self,name,value):
if name == 'square':
self.width = value
self.height = height
else:
self.__dict__[name] = value
def getArea(self):
return self.width * self.height
运行
>>> r1 = Rectangle(4,5)>>> r1.getArea()20
迭代器
还记得迭代吗?
这篇介绍下
迭代类似于循环,每一次充分的过程被称为一次迭代
如序列(列表,元组,字符串),还有字典,都支持迭代操作
复习一下
>>> for i in 'tianjun':... print(i)...tianjun>>>
字符串相当一个容器,也同时是个迭代器,for语句的作用介绍触发这个迭代器的迭代功能,每次拿出一个数据,就是迭代操作
关于迭代
Python有两个BIF
重点
iter()
next()
对一个容器对象调用iter就是得到他的接待器,调用next迭代器觉慧返回下一个值
如果一个容器是迭代器,那就必须调用iter方法,这个方法实际是就是返回迭代器本身,然后是实现的是next()魔法方法,因为它决定了迭代的规则,如下
用迭代器写的裴波那切数列:
class Fibs: def __init__(self,n = 10): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): self.a,self.b = self.b,self.a+self.b if self.a > self.n: raise StopIteration return self.a
生成器、什么是生成器
通过列表生成式,我们可以直接创建一个列表,但是,受到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,称为生成器:generator
继续使用import sys斐波那契
def fibonacci(n): a, b, counter = 0, 1, 0 while True: if (counter > n): return yield a a, b = b, a + b counter += 1f = fibonacci(10) # f 是一个迭代器,由生成器返回生成 while True: try: print (next(f), end=" ") except StopIteration: sys.exit()
输出
0 1 1 2 3 5 8 13 21 34 55
内容是我做的《零基础入门学习Python》笔记
希望大家多多支持原作者