Python相当于C++成员指针

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.但是有更干净的方式吗?

编辑:现在有几个非常好的答案,每个答案根据具体情况提供一些有用的东西.我最终使用了我的答案中描述的内容,但我认为其他答案对于根据问题主题来到这里的人来说非常有帮助.所以,我现在不接受任何一个.

Ulr*_*rdt 7

假设一个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)

关于物业的后续行动,这里有很多答案可以解决这个问题,只要它仍然是一个.

  • 我无法想象你在那儿做什么?以我的经验,我总是需要绑定版本,因此我必须使用SigC ++,Boost.Bind或更高版本的C ++ 11并将函数绑定到对象。还是很有趣,感谢您的反馈!顺便说一句,在Python中,函数和类是一流的对象。这意味着您可以将一个函数附加到一个类上,并且它成为所有实例的方法。另外,您可以从类(上面的MyClass.fn`)中获取一个方法,该方法将成为一个普通函数!函数和方法之间的唯一区别是,第一个参数通常称为“ self”! (2认同)

use*_*ica 5

最贴合的可能是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,fsetfdel,这是实现获得,检索和删除属性管理属性的功能:

example_bar_member = Example.bar.fget
print example_bar_member(example_object) # prints 2
Run Code Online (Sandbox Code Playgroud)

我们没有完成这个属性的设置或删除器,所以fsetfdelNone.这些也是特定类型的; 例如,如果example_bar_member处理列表正确,example_bar_member([])则会引发AttributeError而不是返回2,因为列表没有bar属性.


Chr*_*ern 0

我在 python 中处理这个问题的方法是使用__getattribute__. 如果您有一个属性的名称(类似于 C++ 成员指针),您可以调用a.__getattribute__(x)来获取名称存储在 x 中的属性。它是字符串和字典,而不是偏移量和指针,但这就是Python。