bound与unbound
通常认为实例方法是bound的,而类方法是unbound的,这种说法也没错,只是对于不同类型变量来说,结果是不同的
class A(object):
"""test class"""
_instance = None
def __private(self):
pass
def _protect(self):
pass
def fs(self):
pass
@staticmethod
def sm():
pass
@classmethod
def fc(cls):
pass
测试一下, 结果显示的都是bound method
>>> a = A()
>>> a.fs
<bound method A.fs of <__main__.A object at 0x101fa3250>>
>>> a.fc
<bound method type.fc of <class '__main__.A'>>
直接从类访问,结果fs
这个实例方法显示的是unbound。可以知道bound的意义并不是始终不变的,对于不同的对象来说意义并不一样。
>>> A.fs
<unbound method A.fs>
>>> A.fc
<bound method type.fc of <class '__main__.A'>>
python里面类方法和实例方法可以等价变换
a.fs()
# equals
A.fs(a)
从描述器的角度看
>>> A.__dict__['fs'].__get__(None, A)
<unbound method A.fs>
>>> A.__dict__['fs'].__get__(a, A)
<bound method A.fs of <__main__.A object at 0x101fa3250>>
>>> A.__dict__['fc'].__get__(None, A)
<bound method type.fc of <class '__main__.A'>>
不过实例a
调用静态方法会出错(TypeError),因为实例对方法的调用提供了self
参数,但sm
是没有参数的。但是这提供了另一种思路)比如在python的多进程编程中,进程跑的函数如果是实例函数的会因为无法序列化而失败,但如果是staticmethod
就没有问题,静态函数的本质其实也就是普通函数。
所以可以这样
class B(object):
@staticmethod
def run(inst):
inst.foo()
def foo(self):
print 'foo'
b = B()
B.run(b)
在2.x中区分实例函数和类函数可以用im_self
>>> A.fs.im_self
None
>>> A.fc.im_self
<class '__main__.A'>
至于通过实例引用方法时的im_self
的值,大家自己可以探索下
获取类中所有定义的方法
使用
dir
函数
>>> dir(A)
['_A__private',
'__class__',
'__delattr__',
'__dict__',
'__doc__',
'__format__',
'__getattribute__',
'__hash__',
'__init__',
'__module__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_instance',
'_protect',
'fc',
'fs',
'sm']
2 使用inspect.getmembers
这个除了函数名的字符串以外,连对象的type也得到了,结果更加详细
>>> inspect.getmembers(A)
[('_A__private', <unbound method A.__private>),
('__class__', type),
('__delattr__', <slot wrapper '__delattr__' of 'object' objects>),
('__dict__',
<dictproxy {'_A__private': <function __main__.__private>,
'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': 'test class',
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'_instance': None,
'_protect': <function __main__._protect>,
'fc': <classmethod at 0x1022a50f8>,
'fs': <function __main__.fs>,
'sm': <staticmethod at 0x1022a5088>}>),
('__doc__', 'test class'),
('__format__', <method '__format__' of 'object' objects>),
('__getattribute__', <slot wrapper '__getattribute__' of 'object' objects>),
('__hash__', <slot wrapper '__hash__' of 'object' objects>),
('__init__', <slot wrapper '__init__' of 'object' objects>),
('__module__', '__main__'),
('__new__', <function __new__>),
('__reduce__', <method '__reduce__' of 'object' objects>),
('__reduce_ex__', <method '__reduce_ex__' of 'object' objects>),
('__repr__', <slot wrapper '__repr__' of 'object' objects>),
('__setattr__', <slot wrapper '__setattr__' of 'object' objects>),
('__sizeof__', <method '__sizeof__' of 'object' objects>),
('__str__', <slot wrapper '__str__' of 'object' objects>),
('__subclasshook__', <function __subclasshook__>),
('__weakref__', <attribute '__weakref__' of 'A' objects>),
('_instance', None),
('_protect', <unbound method A._protect>),
('fc', <bound method type.fc of <class '__main__.A'>>),
('fs', <unbound method A.fs>),
('sm', <function __main__.sm>)]
判断某个属性是否可调用
a = A()
callable(getattr(a, 'testattr', None))
获得一个对象中所有可调用的方法
[method for method in dir(object) if callable(getattr(object, method))]
隐藏属性
重写__dict__
或者__dir__
class C(object):
__dict__ = {}
def __dir__(self):
return ['cherry']
注意,这里的__dict__
不是类的,是实例的,类的__dict__
是不可写的,不信可以试试__dir__
很奇怪,如果dir
函数用在C
的实例上,确实会返回['cherry']
,但dir(C)
还是能得到类中所有属性,有点掩耳盗铃的感觉,待继续研究
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。