元类:
python中的类也是对象,元类就是用来创建这些类(对象)的,元类就是类的类
格式:type(类名,父类名称组成的元组(父类名,可为空),包含属性的字典(名字和值))
实际工作中基本用不到,只了解即可
slots
python是动态语言,运行过程中可改变其结构
先看一个例子:
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
p = Person("小王",13)
p.addr = "北京"
print(p.name,p.age,p.addr)
运行结果:
小王 13 北京
可以看到,我们在定义类的时候创建addr属性,那么为什么可以打印出来?这其实就是因为我们动态给实例绑定了属性
如果我想做的程序不想让动态给实例绑定属性,我们该怎么做呢?这就需要__slots__发挥作用了
程序如下:
class Person(object):
__slots__ = ("name","age")
p = Person("小王",13)
p.addr = "北京"
print(p.name,p.age,p.addr)
运行结果:
Traceback (most recent call last):
File "C:/Users/pwrd/AppData/Local/Temp/老王开枪-8-老王开枪.py/jincheng.py", line 4, in <module>
p = Person("小王",13)
TypeError: object() takes no parameters
抛出异常,对象中没有相关参数,这就是__slots__的作用
生成器:
首先,看来看一下生成器概念。在学python的过程中,肯定早就学到了循环,name肯定见过类似于以下的循环语句
for i in range(5):
i += 1
print(i)
那么我们换一种写法来写:
m = [i+1 for i in range(5)]
print(m)
列表m中的值与第一种写法的值是一样的, [i+1 for i in range(5)]这个式子叫做列表生成式,把[]换成()就是我们要说的列表生成器,这是列表生成器的第一种方法
第二种方法:
首先还是先看一个函数循环:
#著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到
def fib(times):#times是次数
n = 0
a = 0
b = 1
while n < times:
print(b)
a,b = b,a+b
n += 1
return "over"
print(fib(5))
想要把函数变为生成器,只要把 print(b),变为yield b即可
#著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到
def fib(times):#times是次数
n = 0
a = 0
b = 1
while n < times:
yield b
a,b = b,a+b
n += 1
return "over"
f = fib(5)
print(next(f))
print(next(f))
print(next(f))
print(next(f))
print(next(f))
运行结果:
1
1
2
3
5
使用__next__方法也可取值
def fib(times):#times是次数
n = 0
a = 0
b = 1
while n < times:
yield b
a,b = b,a+b
n += 1
return "over"
f = fib(5)
for i in range(5):
print(f.__next__())
send的使用:
我们使用yield创建生成器,test函数作用暂时保存,返回i的值,temp接收下一次send发过来的值
例如:
def test():
i = 0
for i in range(5):
temp = yield i
print(temp)
i += 1
t = test()
print(t.__next__())
print(t.send("我是send"))
运行结果:
0
我是send
1
可以看到我是在先打印了一个值的情况下send了一个值给函数,name我可以在生成器开始之前send吗?下面我们试一试
def test():
i = 0
for i in range(5):
temp = yield i
print(temp)
i += 1
t = test()
print(t.send("我是send1"))
print(t.__next__())
print(t.send("我是send2"))
运行结果:
print(t.send("我是send1"))
TypeError: can't send non-None value to a just-started generator
我们看到异常提示不能在生成器开始时send一个不为None的变量,那么为什么使用next后就可以了呢,这是因为next就相当于发送了一个值为None的变量