Python equivalent of C ++ element pointer

What would be the equivalent of a C ++ element pointer in Python? Basically, I would like to be able to reproduce similar behavior in 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)

The next question is, what if an element is a property instead of a method? Is it possible to save / pass a "pointer" to a property without specifying an instance?

One way, obviously, would be to pass the string and use eval. But is there a cleaner way?

EDIT: Now there are some really good answers, each of which has something useful depending on the context. I ended up using what is described in my answer, but I think that other answers will be very useful for those who come here, based on the topic of the question. So, I do not accept any.

+4
source share
5 answers

Assuming a Python class:

class MyClass:
    def __init__(self):
        self.x = 42

    def fn(self):
        return self.x

The equivalent of a C ++ pointer-to-pointer function is as follows:

fn = MyClass.fn

You can call this with an instance, for example in C ++:

o = MyClass()
print(fn(o)) # prints 42

However, it is often more interesting that you can also take the "address" of a related member function that does not work in C ++:

o = MyClass()
bfn = o.fn
print(bfn()) # prints 42, too

Regarding the following actions with properties, there are many answers that touch upon this problem, if it is still one.

+6
source

Most likely it will be 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

attrgetter , , , . , , , , . , ; , attrgetter('count') count , , - count.


, -. , , , :

unbound_baz_method = Example.baz
print unbound_baz_method(example_object) # prints 3

, , , Python. -; list.count , tuple.count .

fget, fset fdel, , , , :

example_bar_member = Example.bar.fget
print example_bar_member(example_object) # prints 2

deleter , fset fdel None. ; , example_bar_member , example_bar_member([]) AttributeError, 2, bar.

+5

. , , :

import types

# Our test class
class Class:

    def __init__(self, val):
        self._val = val

    def method(self):
        return self._val

    @property
    def prop(self):
        return self._val

# Get the member pointer equivalents
m = Class.method
p = Class.prop

# Create an instance
c1 = Class(1)

# Bind the method and property getter to the instance
m1 = types.MethodType(m, c1)
p1 = types.MethodType(p.fget, c1)

# Use
m1()  # Returns 1
p1()  # Returns 1

# Alternatively, the instance can be passed to the function as self
m(c1)  # Returns 1
p.fget(c1)  # Returns 1
+2

++, , , , , , . ( instancemethod Python 2, function Python 3.)

--- , object.reference(args), : reference(object, args). object self --- , .

C-like, , - , ... , , . : , __init__.

:

#!/usr/bin/env python3


import math


class Vector(object):

    def __init__(self, x, y):
        self.x = x
        self.y = y
        return

    def __str__(self):
        return '(' + str(self.x) + ', ' + str(self.y) + ')'

    def __repr__(self):
        return self.__class__.__name__ + str(self)

    def magnitude(self):
        return math.sqrt(self.x ** 2 + self.y ** 2)


def print_dict_getter_demo():
    print('Demo of member references on a Python dict:')
    dict_getter = dict.get
    d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
    print('Dictionary d      :  ' + str(d))
    print("d.get('a')        :  " + str(d.get('a')))
    print("Ref to get 'a'    :  " + str(dict_getter(d, 'a')))
    print("Ref to get 'BOGUS':  " + str(dict_getter(d, 'BOGUS')))
    print('Ref to get default:  ' + str(dict_getter(d, 'BOGUS', 'not None')))
    return


def print_vector_magnitude_demo():
    print('Demo of member references on a user-defined Vector:')
    vector_magnitude = Vector.magnitude
    v = Vector(3, 4)
    print('Vector v        :  ' + str(v))
    print('v.magnitude()   :  ' + str(v.magnitude()))
    print('Ref to magnitude:  ' + str(vector_magnitude(v)))
    return

def print_vector_sorting_demo():
    print('Demo of sorting Vectors using a member reference:')
    vector_magnitude = Vector.magnitude
    v0 = Vector(0, 0)
    v1 = Vector(1, 1)
    v5 = Vector(-3, -4)
    v20 = Vector(-12, 16)
    vector_list = [v20, v0, v5, v1]
    print('Unsorted:  ' + str(vector_list))
    sorted_vector_list = sorted(vector_list, key=vector_magnitude)
    print('Sorted:    ' + str(sorted_vector_list))
    return


def main():
    print_dict_getter_demo()
    print()
    print_vector_magnitude_demo()
    print()
    print_vector_sorting_demo()
    return


if '__main__' == __name__:
    main()

Python 3 :

Demo of member references on a Python dict:
Dictionary d      :  {'a': 1, 'c': 3, 'b': 2, 'z': 26}
d.get('a')        :  1
Ref to get 'a'    :  1
Ref to get 'BOGUS':  None
Ref to get default:  not None

Demo of member references on a user-defined Vector:
Vector v        :  (3, 4)
v.magnitude()   :  5.0
Ref to magnitude:  5.0

Demo of sorting Vectors using a member reference:
Unsorted:  [Vector(-12, 16), Vector(0, 0), Vector(-3, -4), Vector(1, 1)]
Sorted:    [Vector(0, 0), Vector(1, 1), Vector(-3, -4), Vector(-12, 16)]

, , .

Edit:

: , , "" , - .

, :

d = {'a': 1, 'b': 2, 'c': 3, 'z': 26}
d_getter = d.get
d_getter('z')  # returns 26

, , , function method "" self, .

+1

The way I approach this in python is to use __getattribute__. If you have an attribute name that would be analogous to a C ++ C ++ pointer, you can call a.__getattribute__(x)to get an attribute whose name is stored in x. These are strings and dicts instead of offsets and pointers, but this python.

0
source

All Articles