程序在查找变量的定义时遵循LEGB规则
LEGB规则:
locals-->enclosing function-->globals-->builtinslocals当前所在命名空间的变量
enclosing外部嵌套函数的命名空间(闭包中常见)
global全局变量,函数定义所在模块的命名空间
builtins系统自带的,比如;eval,sum,id
object类是基类
python是动态语言,比如一个类,可以在运行过程中随时添加属性,但是c中必须实现定义好
#
#c是静态语言:运行之前先编译
#object是python中最顶层的基类
class Person(object):
def __init__(self,name,age):
self.name=name
self.age=age
def eat(self):
print("can eat")
def run(self):
print("can run")
p1=Person("wangming",10)
p1.eat()
p1.home="jia"
print(p1.home) #python是动态的,所以这里可以添加属性
#但是不可以以下面方式添加方法
#p1.run=run
#p1.run()#error 虽然p1对象run属性已经指向了类外面定义的函数,在新定义的函数中,
#并没有把p1当作参数,导致 在调用中,出现缺少参数的提示
#添加一个对象的实例方法的正确方式
import types
p1.run=types.MethodType(run,p1)#(function,instance),将一个函数绑定到对象上去
p1.run()# can run
Run=types.MethodType(run,p1)
Run()# can run 后面实现绑定,将P1作为参数传递给run函数,self
#返回值是p1.run()的引用
静态方法和类方法可以直接实现添加
#静态方法没有参数,可以直接赋值
@staticmethod
def test():
print("this is a staticmethod ")
Person.test=test
Person.test()#this is a staticmethod
@classmethod
def printClass(cls):
print("this is class methond")
Person.printClass=printClass#相当于将这个方法赋值给类属性
Person.printClass()#this is class method
#给类添加属性,直接添加,但是不能直接赋值的方式给一个实例对象赋值,需要用到types.MethodType()
#这样可以实现在程序没有发生大改变的前提下,实现修改
#
#__slots__()用来限制该class能添加的属性
class Student(object):
__slots__=("name","age")#限制属性,包含属性
st1=Student()
st1.name="xiao"
st1.age=32
#st1.add="d"#这句话是错误的,不允许添加限制之外的属性,不过这个只对当前实例其作用,对继承的子类不起作用
#
生成器
a=(x for x in range(10))#这是一个生成器,可以用next()进行取值
a=100
b=200
a,b=b,a
#print(a,b) #200,100
#
#函数中有yeild时,不能当成普通的函数,而是生成器
#生成器并不是一次开辟很多的空间,而是每次运行一次
#
def creatNum():
a,b=0,1
for i in range(10):
yield b #这个是每次的返回值
a,b=b,a+b
#创建 一个生成器对象
a=creatNum()
#可以使用next的方式打印返回值
#函数执行到yield,系统暂停,返回函数值
ret=a.__next__()
print(ret)
print(next(a))
print("----------")
'''
for num in a:#上面的生成器可以用next()获取下一个返回值,但是会有个条件来确定结束,这里有for循环迭代
print(num)#打印出来斐波那契数列
for nu in creatNum():
print(nu)
'''
'''
1
1
----------
2
3
5
8
13
21
34
55
1
1
2
3
5
8
13
21
34
55
'''
yield的用法
def Generator():
i=0
while i<5:
temp=yield i
print(temp)#temp相当于是yeild i 的整体赋给temp,如果没有值传递,为空
i+=1
t=Generator()
#print(t.send("这里不能刚开始就传值"))#系统还没运行到这里
#1 第一次先调用t.__next__(),再调用t.send("xxx")
#2 或者t.send(None)
#如果程序没有给temp赋值,则temp将保留上一次的值
print(t.__next__())#0
print(t.__next__())#None 1
print(t.__next__())#None 2
print(t.send("hello"))#hello 3