And*_*bis 6 python pointers member
什么是Python中的C++成员指针的等价物?基本上,我希望能够在Python中复制类似的行为:
// Pointer to a member of MyClass
int (MyClass::*ptMember)(int) = &MyClass::member;
// Call member on some instance, e.g. inside a function to
// which the member pointer was passed
instance.*ptMember(3)
Run Code Online (Sandbox Code Playgroud)
跟进问题,如果成员是属性而不是方法怎么办?是否可以在不指定实例的情况下将"指针"存储/传递给属性?
一种方法显然是传递一个字符串并使用eval.但是有更干净的方式吗?
编辑:现在有几个非常好的答案,每个答案根据具体情况提供一些有用的东西.我最终使用了我的答案中描述的内容,但我认为其他答案对于根据问题主题来到这里的人来说非常有帮助.所以,我现在不接受任何一个.
假设一个Python类:
class MyClass:
def __init__(self):
self.x = 42
def fn(self):
return self.x
Run Code Online (Sandbox Code Playgroud)
那么C++指向成员函数的等价物如下:
fn = MyClass.fn
Run Code Online (Sandbox Code Playgroud)
您可以使用C++中的实例来调用它:
o = MyClass()
print(fn(o)) # prints 42
Run Code Online (Sandbox Code Playgroud)
但是,通常更有趣的是,您还可以使用绑定成员函数的"地址",这在C++中不起作用:
o = MyClass()
bfn = o.fn
print(bfn()) # prints 42, too
Run Code Online (Sandbox Code Playgroud)
关于物业的后续行动,这里有很多答案可以解决这个问题,只要它仍然是一个.
最贴合的可能是operator.attrgetter:
from operator import attrgetter
foo_member = attrgetter('foo')
bar_member = attrgetter('bar')
baz_member = attrgetter('baz')
class Example(object):
def __init__(self):
self.foo = 1
@property
def bar(self):
return 2
def baz(self):
return 3
example_object = Example()
print foo_member(example_object) # prints 1
print bar_member(example_object) # prints 2
print baz_member(example_object)() # prints 3
Run Code Online (Sandbox Code Playgroud)
attrgetter通过完全相同的机制,正常的点线访问通过,所以它适用于你用点访问的任何东西.实例字段,方法,模块成员,动态计算属性等等.无论物体的类型是什么都无关紧要; 例如,attrgetter('count')可以使用count属性检索列表,元组,字符串或任何其他内容的count属性.
对于某些类型的属性,可能会有更具体的成员指针式事物.例如,对于实例方法,您可以检索未绑定的方法:
unbound_baz_method = Example.baz
print unbound_baz_method(example_object) # prints 3
Run Code Online (Sandbox Code Playgroud)
这可以是实现该方法的特定函数,也可以是函数周围非常薄的包装器,具体取决于您的Python版本.它是特定类型的; list.count不适用于元组,tuple.count也不适用于列表.
对于属性,您可以检索属性对象的fget,fset和fdel,这是实现获得,检索和删除属性管理属性的功能:
example_bar_member = Example.bar.fget
print example_bar_member(example_object) # prints 2
Run Code Online (Sandbox Code Playgroud)
我们没有完成这个属性的设置或删除器,所以fset和fdel是None.这些也是特定类型的; 例如,如果example_bar_member处理列表正确,example_bar_member([])则会引发AttributeError而不是返回2,因为列表没有bar属性.
我在 python 中处理这个问题的方法是使用__getattribute__. 如果您有一个属性的名称(类似于 C++ 成员指针),您可以调用a.__getattribute__(x)来获取名称存储在 x 中的属性。它是字符串和字典,而不是偏移量和指针,但这就是Python。