python语法笔记(四)
1、对象的属性
python一切皆对象,每个对象都可能有多个属性。python的属性有一套统一的管理方案。
属性的__dict__系统
对象的属性可能来自于其类定义,叫做类属性;还可能是该对象实例自身定义的属性,叫做对象属性。类属性可能来自类定义自身,也可能根据定义继承而来。
对象的属性存储在对象的__dict__属性中,__dict__是一个词典,键为属性名,值为属性本身。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Bird( object ): feather = True class Chicken(Bird): fly = False def __init__( self , age): self .age = age summer = chicken( 2 ) print Bird.__dict__ print Chicken.__dict__ print summer.__dict__ { '__dict__' : <attribute '__dict__' of 'Bird' objects>, '__module__' : '__main__' , '__weakref__' : <attribute '__weakref__' of 'Bird' objects>, 'feather' : True , '__doc__' : None } { 'fly' : False , '__module__' : '__main__' , '__doc__' : None , '__init__' : <function __init__ at 0x2b91db476d70 >} { 'age' : 2 } |
可以看出,对类或对象(实际类也是一类对象)调用__dict__方法,只是返回该类或对象新增的属性。如果只有一个对象,而不知道它的类以及其他信息的时候,可以利用__class__属性找到对象的类,然后调用类的__base__属性来查询父类。
可以通过__dict__来获取和设置对象的属性。
1 2 3 4 5 | summer.__dict__[ 'age' ] = 3 print (summer.__dict__[ 'age' ]) summer.age = 5 print (summer.age) |
使用特殊方法__getattr__
可以使用 __getattr__(self, name) 来查询即时生成的属性,当我们查询一个属性的时候,如果通过__dict__方法无法找到该属性,那么python会调用该对象的__getattr__方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class bird( object ): feather = True class chicken(bird): fly = False def __init__( self , age): self .age = age def __getattr__( self , name): if name = = 'adult' : if self .age > 1.0 : return True else : return False else : raise AttributeError(name) summer = chicken( 2 ) print (summer.adult) summer.age = 0.5 #本身有age属性 print (summer.adult) #本省没有age属性,会调用__getattr__方法 print (summer.male) #本省没有age属性,会调用__getattr__方法,抛出异常 每个特性需要有自己的处理函数,而__getattr__可以将所有的即时生成属性放在同一个函数中处理。__getattr__可以根据函数名区别处理不同的属性。<br>比如上面我们查询属性名male的时候, raise AttributeError。 |
python中还有一个__getattribute__特殊方法,用于查询任意属性,而__getattr__只能用来查询不在__dict__系统中的属性。
2、闭包
函数对象作用域
python中函数也是对象,函数对象也有其存活的范围,就是函数对象的作用域。函数对象用def语句定义,函数对象的作用域与def所在的层级相同。比如,在函数A中定义内部函数B,内部函数B只能在定义该函数A内部使用,不能在函数A外部使用。
1 2 3 4 5 6 7 8 | def line_conf(): def line(x): return 2 * x + 1 print (line( 5 )) # within the scope line_conf() print (line( 5 )) # out of the scope |
如果使用lambda定义函数,那么函数对象的作用域与lambda所在的层级相同。
闭包
函数是一个对象,所以可以作为某个函数的返回结果。
1 2 3 4 5 6 7 8 9 | def line_conf(): b = 15 def line(x): return 2 * x + b return line # return a function object b = 5 my_line = line_conf() print (my_line( 5 )) |
line定义的隶属程序块中引用了高层级的变量b,但b信息存在于line的定义之外,成b为line的环境变量。line作为line_conf的返回值时,line中已经包含了b的取值(尽管b并不隶属于line).
一个函数和它的环境变量合在一起就构成了一个闭包。在python中,闭包就是一个包含有环境变量取值的函数对象,环境变量取值被保存在函数对象的__closure__属性中。比如:
1 2 3 4 5 6 7 8 9 10 | def line_conf(): b = 15 def line(x): return 2 * x + b return line # return a function object b = 5 my_line = line_conf() print (my_line.__closure__) print (my_line.__closure__[ 0 ].cell_contents) |
__closure__里包含了一个元组,该元组中的每个元素都是cell类型的对象。
1 2 3 4 5 6 7 8 9 10 | def line_conf(a, b): def line(x): return ax + b return line line1 = line_conf( 1 , 1 ) line2 = line_conf( 4 , 5 ) print (line1( 5 ), line2( 5 )) 只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到, 闭包也具有提高代码可复用性的作用。 |
3、装饰器
装饰器是一种高级的python语法,装饰器可以对一个函数、方法或者类进行加工。
(1)装饰函数和方法
装饰器经常用于对一些函数添加这些函数需要共同执行的一些操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #定义装饰器函数,装饰器名任意 def decorator(F): def new_F(a, b): print ( "input" , a, b) return F(a, b) return new_F #返回一个可调用对象,该可调用对象以函数为参数 # get square sum @decorator #使用装饰器进行装饰,在前面使用 @装饰器名 def square_sum(a, b): return a * * 2 + b * * 2 # get square diff @decorator def square_diff(a, b): return a * * 2 - b * * 2 print (square_sum( 3 , 4 )) print (square_diff( 3 , 4 )) #使用装饰器的效果等同于,将函数重定义 square_sum = decorator(square_sum) square_sum( 3 , 4 ) |
(2)含参的装饰器
装饰器允许我们在调用装饰器的时候提供其他参数,比如 @decorator(params..)
1 2 3 4 5 6 7 8 9 10 11 12 13 | #a new wrapper layer def pre_str(pre = ''): #old decorator def decorator(F): def newF(a, b): print (pre + 'intput' , a, b) return F(a,b) return newF return decorator @pre_str ( 'xxxfjdflsd' ) #提供装饰器参数 def square_num(a, b): return a * * 2 + b * * 2 |
(3)装饰类
一个装饰器可以接收一个类,并返回一个类,达到加工类的效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def decorator(aClass): class newClass( object ): def __init__( self , age): self .total_display = 0 self .wrapped = aClass(age) def display( self ): self .total_display + = 1 print ( 'total display' , self .total_display) self .wrapped.display() return newClass @decorator class Bird( object ): def __init__( self , age): self .age = age def display( self ): print ( 'my age is' , self .age) eagleLord = Bird( 5 ) for i in range ( 3 ): eagleLord.dislay() |
参考:
http://www.cnblogs.com/vamei/archive/2012/09/13/2682778.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】凌霞软件回馈社区,携手博客园推出1Panel与Halo联合会员
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 长文讲解 MCP 和案例实战
· Hangfire Redis 实现秒级定时任务,使用 CQRS 实现动态执行代码
· Android编译时动态插入代码原理与实践
· 解锁.NET 9性能优化黑科技:从内存管理到Web性能的最全指南
· 一天 Star 破万的开源项目「GitHub 热点速览」
· 记一次 .NET某旅行社酒店管理系统 卡死分析
· 别再堆文档了,大模型时代知识库应该这样建
· C#/.NET/.NET Core技术前沿周刊 | 第 35 期(2025年4.14-4.20)
· 上周热点回顾(4.14-4.20)