python核心编程:元类,__slots__,生成器,send

元类:
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的变量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值