简体   繁体   中英

Python analog to C++ pointer to class member

Is it possible to create pointer to Python class member (not method)?

I want something like this:

class PClass:
    def __init__(self):
        self.a = 123
    def foo(self, a):
        self.a = a

# this works
def bar(pointer_to_method):
    py_ex = PClass()
    pointer_to_method(py_ex, 321)
bar(PClass.foo)

# this does not
def boo(pointer_to_member):
    py_ex = PClass()
    py_ex.pointer_to_member = 321

boo(PClass.a)

In C++ I can create pointer both class member and class functions

class CClass
{
public:
    int CClass_property_1;
    int CClass_property_2;
    void CClass_method(const int& param){}
};
auto method_pointer = &CClass::CClass_method;
auto propery_1_pointer = &CClass::CClass_property_1;
propery_1_pointer = &CClass::CClass_property_2;

Now I can use instance of CClass to call functions from the pointers, or to get access to the properties.

I am interested in Python analog to C++ pointer to class properties (not methods)

Python is totally different from C++ when it comes to memory model and what "variables" really are, so your question doesn't really make sense. I strongly suggest you read this to understand why the mere concept of "pointer" doesn't apply in Python.

wrt/ your python snippet:

class PClass:
    def __init__(self):
        self.a = 123
    def foo(self, a):
        self.a = a

# this works
def bar(pointer_to_method):
    py_ex = PClass()
    pointer_to_method(py_ex, 321)

bar(PClass.foo)

this works because PClass.foo evals to either an unbound method (python2.x) or just directly to the foo function (yes, "function" - cf https://wiki.python.org/moin/FromFunctionToMethod ) - but in both cases to a callable object that is either your function or a small wrapper around it.

# this does not
def boo(pointer_to_member):
    py_ex = PClass()
    py_ex.pointer_to_member = 321

boo(PClass.a)

This cannot work as is for the obvious reason that a is not an attribute of the PClass class object but of PClass instances, so here you get an AttributeError.

Now even if you try quamrana's snippet (using a PClass instance), you'll pass the AttributeError issue but the code will still not work, ie this:

def boo(pointer_to_member):
    pointer_to_member = 321

instance = PClass()
boo(instance.a)

will not raise an error, but it will still not update instance.a . The reasons here are the topic of the whole article I linked to so I won't get to much into details but to make a long story short, a python variable is just a name, it's not a memory address, so in the above code, instance.a is first eval'd, and the value (the int instance bound to instance.a ) is passed to boo() under the name "pointer_to_member". This name is a local name, so rebinding it only affect the function's local namespace, at this point the code knows absolutely nothing of instance nor of it's a attribute.

Now if you cared to explain the problem you're trying to solve here, we could certainly point you to the proper pythonic solution. The point is: trying to write C++ in Python is just as useless as trying to write Python in C++ - different languages, different idioms and patterns.

So Class have methods, but does not have members ? While instance of class have both?

In Python we say "attributes", not "members". And yes, classes can have attributes too (classes ARE objects, instances of the type class), but those are shared between all instances of the class. FWIW, "methods" are actually class attributes (yes, functions are objects too - actually just everything is an object - and they don't live in a distinct namespace).

Also, instances do not "have" methods per se - the methods are attributes of the class object (it's actually the case too in C++ FWIW) -, but Python's attribute lookup rules (the code that is invoked on a 'dotted' access) look for the name in the class (and it's parents) if it's not found on the instance itself. You can read the second article I linked to for more on what Python "methods" really are (the article would need an update to reflects Python3's changes, but is still mostly accurate, except for what Class.methodname yields).

It seems that you are mixing classes and instances . The difference is clearer in Python than in C++.

Here is a rewrite of your code:

class PClass:
    def __init__(self):
        self.a = 123
    def foo(self, a):
        self.a = a


def bar(pointer_to_method):
    pointer_to_method(321)

def boo(pointer_to_member):
    pointer_to_member = 321

instance = PClass()

bar(instance.foo)  # Note that I pass foo bound to instance in the one parameter

boo(instance.a) # Again the member a is bound to instance in the one parameter

At no time does PClass ever have an a member. However, each instance of PClass has an a member because the initialiser creates one.

Update

But as @Bruno has pointed out, the function boo above does nothing, so maybe you want something different:

def zoo(inst, member_name):
    setattr(inst, member_name, 322)

# call like this:
zoo(instance, "a")

This is still not a pointer-to-member as C++ has, but it may be what you are looking for.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM