python的描述符
Ⅰ 请问python描述符property中的self.fget(instance)怎么理解
self.fget等价于 __init__(self,fget=None,fset=None,fdel=None) 方法中的 fset参数
==================看这下面=================================
class C:
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)
执行上面的语句后self.fget就等于类C里的getX
self.fget(instance)等价于调用C里的getX(instance)方法
===========我是新手刚看到这如有兴趣可共同学习================
Ⅱ python 函数是不是描述符
在Python中,访问一个属性的优先级顺序按照如下顺序:
1.类属性
2.数据描述符
3.实例属性
4.非数据描述符
5.__getattr__()方法。这个方法的完整定义如下所示:
[python] view plain
def __getattr__(self,attr) :#attr是self的一个属性名
pass;
先来阐述下什么叫数据描述符。
数据描述符是指实现了__get__,__set__,__del__方法的类属性(由于Python中,一切皆是对象,所以你不妨把所有的属性也看成是对象)
PS:个人觉得这里最好把数据描述符等效于定义了__get__,__set__,__del__三个方法的接口。
阐述下这三个方法:
__get__的标准定义是__get__(self,obj,type=None),它非常接近于JavaBean的get
第一个函数是调用它的实例,obj是指去访问属性所在的方法,最后一个type是一个可选参数,通常为None(这个有待于进一步的研究)
例如给定类X和实例x,调用x.foo,等效于调用:
type(x).__dict__["foo"].__get__(x,type(x))
调用X.foo,等效于调用:
type(x).__dict__["foo"].__get__(None,type(x))
第二个函数__set__的标准定义是__set__(self,obj,val),它非常接近于JavaBean的set方法,其中最后一个参数是要赋予的值
第三个函数__del__的标准定义是__del__(self,obj),它非常接近Java中Object的Finailize()方法,指
Python在回收这个垃圾对象时所调用到的析构函数,只是这个函数永远不会抛出异常。因为这个对象已经没有引用指向它,抛出异常没有任何意义。
接下来,我们来一一比较这些优先级.
首先来看类属性
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class A(object):
foo=3
print A.foo
a=A()
print a.foo
a.foo=4
print a.foo
print A.foo
上面这段代码的输出如下:
3
3
4
3
从输出可以看到,当我们给a.foo赋值的时候,其实与类实例的那个foo是没有关系的。a.foo=4 这句话给a对象增加了一个属性叫foo。其值是4。
最后两个语句明确的表明了,我们输出a.foo和A.foo的值,他们是不同的。
但是为什么a=A()语句后面的print
a.foo输出了3呢?这是因为根据搜索顺序找到了类属性。当我们执行a.foo=4的时候,我们让a对象的foo属性指向了4这个对象。但是并没有改变
类属性foo的值。所以最后我们print A.foo的时候,又输出了3。
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class A(object):
foo=3
a=A()
a.foo=4
print a.foo
del a.foo
print a.foo
上面的代码,我给a.foo赋值为4,在输出一次之后就del了。两次输出,第一次输出的是a对象的属性。第二次是类属性。不是说类属性的优先级比
实例属性的高吗。为啥第一次输出的是4而不是3呢?还是上面解释的原因。因为a.foo与类属性的foo只是重名而已。我们print
a.foo的时候,a的foo指向的是4,所以输出了4。
------------------------------------
然后我们来看下数据描述符这一全新的语言概念。按照之前的定义,一个实现了__get__,__set__,__del__的类都统称为数据描述符。我们来看下一个简单的例子。
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None):
pass
def __set__(self,obj,val):
pass
def __del__(self,obj):
pass
class A(object):
foo=simpleDescriptor()
print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo
上面例子的输出结果如下:
[plain] view plain
{'__dict__': <attribute '__dict__' of 'A' objects>, '__mole__': '__main__', 'foo': <__main__.simpleDescriptor object at 0x005511B0>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
None
None
None
从输出结果看出,print语句打印出来的都是None。这说明a.foo都没有被赋值内容。这是因为__get__函数的函数体什么工作都没有做。直接是pass。此时,想要访问foo,每次都没有返回内容,所以输出的内容就是None了。
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None):
return "hi there"
def __set__(self,obj,val):
pass
def __del__(self,obj):
pass
class A(object):
foo=simpleDescriptor()
print str(A.__dict__)
print A.foo
a=A()
print a.foo
a.foo=13
print a.foo
把__get__函数实现以下,就可以得到如下输出结果:
[plain] view plain
{'__dict__': <attribute '__dict__' of 'A' objects>, '__mole__': '__main__', 'foo': <__main__.simpleDescriptor object at 0x00671190>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
hi there
hi there
hi there
为了加深对数据描述符的理解,看如下例子:
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = 13;
print a.foo;
上面代码的输出是
16
6
第一个16为我们在对a.foo赋值的时候,人为的将13加上3后作为foo的值,第二个6是我们在返回a.foo之前人为的将它减去了10。
所以我们可以猜测,常规的Python类在定义get,set方法的时候,如果无特殊需求,直接给对应的属性赋值或直接返回该属性值。如果自己定义类,并且继承object类的话,这几个方法都不用定义。
-----------------
在这里看一个题外话。
看代码
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __init__(self):
self.result = None;
def __get__(self, obj, type=None) :
return self.result - 10;
def __set__(self, obj, val):
if isinstance(val,str):
assert False,"int needed! but get str"
self.result = val + 3;
print self.result;
def __del__(self, obj):
pass
class A(object):
foo = simpleDescriptor();
a = A();
a.foo = "13";
print a.foo;
上面代码在__set__ 函数中检查了参数val,如果val是str类型的,那么要报错。这就实现了我们上一篇文章中要实现的,在给属性赋值的时候做类型检查的功能。
-----------------------------------------------
下面我们来看下实例属性和非数据描述符。
[python] view plain
# -*- coding:utf-8 -*-
'''''
Created on 2013-3-29
@author: naughty
'''
class B(object):
foo = 1.3
b = B()
print b.__dict__
b.bar = 13
print b.__dict__
print b.bar
上面代码输出结果如下:
{}
{'bar': 13}
13
那么什么是非数据描述符呢?
简单的说,就是没有实现get,set,del三个方法的所有类。
让我们任意看一个函数的描述:
def call():
pass
执行print dir(call)会得到如下结果:
[plain] view plain
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__mole__', '__name__', '__new__', '__rece__', '__rece_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
先看下dir的帮助。
dir列出给定对象的属性或者是从这个对象能够达到的对象。
回到print dir(call)方法的输出,看到,call方法,有输出的那么多个属性。其中就包含了__get__函数。但是却没有__set__和__del__函数。所以所有的类成员函数都是非数据描述符。
看一个实例数据掩盖非数据描述符的例子:
[python] view plain
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type
class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo
看输出:
('get', <__main__.simpleDescriptor object at 0x02141190>,
<__main__.D object at 0x025CAF50>, <class '__main__.D'>)
15
可见,实例数据掩盖了非数据描述符。
如果改成数据描述符,那么就不会被覆盖了。看下面:
[python] view plain
'''''
Created on 2013-3-29
@author: naughty
'''
class simpleDescriptor(object):
def __get__(self,obj,type=None) :
return "get",self,obj,type
def __set__(self,obj,type=None) :
pass
def __del__(self,obj,type=None) :
pass
class D(object):
foo=simpleDescriptor()
d=D()
print d.foo
d.foo=15
print d.foo
代码的输出如下:
[plain] view plain
('get', <__main__.simpleDescriptor object at 0x01DD1190>, <__main__.D object at 0x0257AF50>, <class '__main__.D'>)
('get', <__main__.simpleDescriptor object at 0x01DD1190>, <__main__.D object at 0x0257AF50>, <class '__main__.D'>)
由于是数据描述符,__set __函数体是pass,所以两次输出都是同样的内容。
最后看下__getatrr__方法。它的标准定义是:__getattr__(self,attr),其中attr是属性名
Ⅲ python类的属性有哪几种如何访问它们
属性的访问机制
一般情况下,属性访问的默认行为是从对象的字典中获取,并当获取不到时会沿着一定的查找链进行查找。例如a.x的查找链就是,从a.__dict__['x'],然后是type(a).__dict__['x'],再通过type(a)的基类开始查找。
若查找链都获取不到属性,则抛出AttributeError异常。
一、__getattr__方法
这个方法是当对象的属性不存在是调用。如果通过正常的机制能找到对象属性的话,不会调用__getattr__方法。
classA:
a=1
def__getattr__(self,item):
print('__getattr__call')
returnitem
t=A()
print(t.a)
print(t.b)
#output
1
__getattr__call
b
二、__getattribute__方法
这个方法会被无条件调用。不管属性存不存在。如果类中还定义了__getattr__,则不会调用__getattr__()方法,除非在__getattribute__方法中显示调用__getattr__()或者抛出了AttributeError。
classA:
a=1
def__getattribute__(self,item):
print('__getattribute__call')
raiseAttributeError
def__getattr__(self,item):
print('__getattr__call')
returnitem
t=A()
print(t.a)
print(t.b)
所以一般情况下,为了保留__getattr__的作用,__getattribute__()方法中一般返回父类的同名方法:
def__getattribute__(self,item):
returnobject.__getattribute__(self,item)
使用基类的方法来获取属性能避免在方法中出现无限递归的情况。
三、__get__方法
这个方法比较简单说明,它与前面的关系不大。
如果一个类中定义了__get__(),__set__()或__delete__()中的任何方法。则这个类的对象称为描述符。
classDescri(object):
def__get__(self,obj,type=None):
print("callget")
def__set__(self,obj,value):
print("callset")
classA(object):
x=Descri()
a=A()
a.__dict__['x']=1#不会调用__get__
a.x#调用__get__
如果查找的属性是在描述符对象中,则这个描述符会覆盖上文说的属性访问机制,体现在查找链的不同,而这个行文也会因为调用的不同而稍有不一样:
- 如果调用是对象实例(题目中的调用方式),a.x则转换为调用:。type(a).__dict__['x'].__get__(a, type(a))
- 如果调用的是类属性,A.x则转换为:A.__dict__['x'].__get__(None, A)
其他情况见文末参考资料的文档
- 这个调用也属于无条件调用,这点与__getattribute__一致。区别在于__getitem__让类实例允许[]运算,可以这样理解:
- __getattribute__适用于所有.运算符;
- __getitem__适用于所有[]运算符。
- classA(object):
- a=1
- def__getitem__(self,item):
- print('__getitem__call')
- returnitem
- t=A()
- print(t['a'])
- print(t['b'])
- def__getitem(self,item):
- returnobject.__getattribute__(self,item)
- classC(object):
- a='abc'
- def__getattribute__(self,*args,**kwargs):
- print("__getattribute__()iscalled")
- returnobject.__getattribute__(self,*args,**kwargs)
- #return"haha"
- def__getattr__(self,name):
- print("__getattr__()iscalled")
- returnname+"fromgetattr"
- def__get__(self,instance,owner):
- print("__get__()iscalled",instance,owner)
- returnself
- def__getitem__(self,item):
- print('__getitem__call')
- returnobject.__getattribute__(self,item)
- deffoo(self,x):
- print(x)
- classC2(object):
- d=C()
- if__name__=='__main__':
- c=C()
- c2=C2()
- print(c.a)
- print(c.zzzzzzzz)
- c2.d
- print(c2.d.a)
- print(c['a'])
- 可以结合输出慢慢理解,这里还没涉及继承关系呢。总之,每个以__get为前缀的方法都是获取对象内部数据的钩子,名称不一样,用途也存在较大的差异,只有在实践中理解它们,才能真正掌握它们的用法。
四、__getitem__方法
如果仅仅想要对象能够通过[]获取对象属性可以简单的:
总结
当这几个方法同时出现可能就会扰乱你了。我在网上看到一份示例还不错,稍微改了下:
Ⅳ fluent python是什么意思
《Fluent Python》是一本介绍Python的书。这本书并不是一本完备的 Python 使用手册,而是会强调 Python 作为编程语言独有的特性,这些特性或者是只有 Python 才具备的,或者是在其他大众语言里很少见的。 Python语言核心以及它的一些库会是本书的重点。
相关推荐:《Python基础教程》
目标读者:
正在使用 Python,又想熟悉 Python 3 的程序员 。
主题:
第一部分:
第一部分只有单独的一章,讲解的是 Python 的数据模型(data model),以及如何为了保证行为一致性而使用特殊方法(比如 __repr__),毕竟 Python 的一致性是出了名的。其实整本书几乎都是在讲解 Python 的数据模型,第 1 章算是一个概览。
第二部分:
第二部分包含了各种集合类型:序列(sequence)、映射(mapping)和集合(set),另外还提及了字符串(str)和字节序列(bytes)的区分。说起来,最后这一点也是让亲者(Python 3 用户)快,仇者(Python 2 用户)痛的一个关键,因为这个区分致使 Python 2 代码迁移到 Python 3 的难度陡增。第二部分的目标是帮助读者回忆起 Python内置的类库,顺带解释这些类库的一些不太直观的地方。具体的例子有 Python 3 如何在我们观察不到的地方对 dict 的键重新排序,或者是排序有区域(locale)依赖的字符串时的注意事项。为了达到本部分的目标,有些地方的讲解会比较大而全,像序列类型和映射类型的变种就是这样;有时则会写得很深入,比方说我会对 dict 和 set 底层的散列表进行深层次的讨论。
第三部分:
第三部分首先会解释,如何把函数作为一等对象(first-order object)来使用,然后话题延伸到这个概念对那些被广泛使用的设计模型的影响,最后读者会看到如何利用闭包(closure)的概念来实现函数装饰器(function decorator)。这一部分的话题还包括 Python 的这些基本概念:可调用(callable)、函数属性(functionattribute)、内省(introspection)、参数注解(parameter annotation)和 Python 3 里新出现的 nonlocal 声明。
第四部分:
到了这里,书的重点转移到了类的构建上面。虽然在第二部分里的例子里就有类声明(class declaration)的出现,但是第四部分会呈现更多的类。和任何面向对象语言一样,Python 还有些自己的特性,这些特性可能并不会出现在你我学习基于类的编程的语言中。这一部分的章节解释了引用(reference)的原理、 “可变性”的概念、实例的生命周期、如何构建自定义的集合类型和 ABC、多重继承该怎么理顺、什么时候应该使用操作符重载及其方法。
第五部分:
Python 中有些结构和库不再满足于诸如条件判断、循环和子程序(subroutine)之类的顺序控制流程,第五部分的笔墨会集中在这些构造和库上。我们会从生成器(generator)起步,然后话题会转移到上下文管理器(context manager)和协程(coroutine),其中会涵盖新增的功能强大但又不容易理解的 yield from 语法。这一部分以并发性和面向事件的 I/O 来结尾,其中跟并发性相关的是 collections.futures 这个很新的包,它借助futures 包把线程和进程的概念给封装了起来;而跟面向事件 I/O 相关的则是 asyncio,它的背后是基于协程和 yield from 的 futures 包。
第六部分:
第六部分的开头会讲到如何动态创建带属性的类,用以处理诸如JSON这类半结构化的数据。然后会从大家已经熟悉的特性(property)机制入手,用描述符从底层来解释Python对象属性的存取。同时,函数、方法和描述符的关系也会被梳理一遍。第六部分会从头至尾地实现一个字段验证器,在这个过程中我们会遇到一些微妙的问题,然后在最后一章中就自然引出像类装饰器(class decorator)和元类(metaclass)这些高级的概念。
Ⅳ python中用fileno没返回文件描述符,请问是怎么回事
这个就是啊,你应该用一个变量来接收返回值,然后用变量来操作文件。
Ⅵ python高级编程技巧实战怎么样
bobby《Python3高级核心技术97讲》(超清视频)网络网盘
链接: https://pan..com/s/1iJ9VvVE3Km_x4-RCfI5Anw
若资源有问题欢迎追问~
Ⅶ python的标识符有哪些
python函数的变量名,函数名都是标识符标识符遵循4点规则1 。标识符由字母、下划线和数字组成2 。不能以数字开头3 。区分大小写4 。不能使用关字
定律是为实践和事实所证明,反映事物在一定条件下发展变化的客观规律的论断。定律是一种理论模型,它用以描述特定情况、特定尺度下的现实世界,在其它尺度下可能会失效或者不准确。
没有任何一种理论可以描述宇宙当中的所有情况,也没有任何一种理论可能完全正确。人生同样有其客观规律可循。
一、生活定律 痛苦定律:死无疑是痛苦的,然而还有比死更痛苦的东西,那就是等死。
幸福定律:如果你不再总是想着自己是否幸福时,你就获得幸福了。
错误定律:人人都会有过失,但是,只有重复这些过失时,你才犯了错误。
沉默定律:在辩论时,沉默是一种最难驳倒的观点。
动力定律:动力往往只是起源于两种原因:希望,或者绝望。
受辱定律:受辱时的唯一办法是忽视它,不能忽视它时就藐视它;如果连藐视它也不能,那么你就只能受辱了。
愚蠢定律:愚蠢大多是在手脚或舌头运转得比大脑还快的时候产生的。
化妆定律:在修饰打扮上花费的时间有多少,你就需要掩饰的缺点也就有多少。
省时定律:要想学会最节省时间的办法,首先就需要学会说"不"。
地位定律:有人站在山顶上,有人站在山脚下,虽然所处的地位不同,但在两者的眼中所看到的对方,却是同样大小的。
失败定律:失败并不以为着浪费时间与生命,却往往意味着你又有理由去拥有新的时间与生命了。
谈话定律:最使人厌烦的谈话有两种:从来不停下来想想;或者,从来也不想停下来。
误解定律:被某个人误解,麻烦并不大;被许多人误解,那麻烦就大了。
结局定律:有一个可怕的结局,也比不上没有任何结局可怕。
二、工作定律
安全定律:最安全的单位几十年没有得过安全奖(最安全证明你们安全没有做工作)
需要定律:同样两个相同的单位,同样的办公费。多少年以后,发生了变化(证明你们单位办公不需要那么多的钱)出来反对,这种成功的概论会归结为零。
评比定律:领导认为谁好,谁就好。(只要领导看你不顺眼,再辛辛苦苦地工作也是白费力气。)
一票否决定律:在一个单位,比如升工资,比如提拔任用,一个人提出来,往往成功的概率最大,而另一个人站
接受教育定律:每个单位都有吊儿郎当不好好干工作的人。但领导往往在批评这些人的时候,这些人恰恰不在场,于是,便出现了遵纪守法的人,经常接受教育的尴尬局面。
哭闹定律;那个部门没有几个因为经常的哭闹而得到了实惠,他有什么理由不经常哭闹下去。(此定理也适用那些经常在领导面前叫苦叫累的部门)
能者多劳定律:在同一科室里,有的人虽然在其岗,但却不能胜任本职工作,那他的工作只能由能胜任该项工作的人去代劳。
不平衡定律:年年当先进的部门或个人,一年没有当先进便想不通;从未当先进的部门或个人,当上先进后便想不到。
少劳多得定律:一般的单位,都分为合同工、(过去称为正式工)协议工、临时工等等。拿钱越少的工作量越大,而且越容易被解雇;拿钱越多的越没有多少事情可干,而且最不容易被解雇。
Ⅷ python中w、r表示什么意思
文件读写就是一种常见的IO操作。
文件读写操作步骤
不同的编程语言读写文件的操作步骤大体都是一样的,都分为以下几个步骤:
1)打开文件,获取文件描述符;
2)操作文件描述符--读/写;
3)关闭文件。
相关推荐:《Python教程》
文件打开模式:
r+、w+和a+都可以实现对文件的读写,那么他们有什么区别呢?
r+会覆盖当前文件指针所在位置的字符,如原来文件内容是"Hello,World",打开文件后写入"hi"则文件内容会变成"hillo, World"。
w+与r+的不同是,w+在打开文件时就会先将文件内容清空,不知道它有什么用。
a+与r+的不同是,a+只能写到文件末尾(无论当前文件指针在哪里)。