What is the function substituting class member access? - python

For example, we have a class:
class A:
def __init__(self, a):
self.a = a
what is the function call to replace:
A.a
I want to apply it with map function.

Your question is not very clear but if you want to change the value of A.a in python it is as simple as
A.a = "New Value"
From what I've read from the python documentation, it seems that you can do that without the need of setter() and getter() function like other languages. I took this example from the link hyperlinked above.
class Employee:
pass
john = Employee() # Create an empty employee record
# Fill the fields of the record
john.name = 'John Doe'
john.dept = 'computer lab'
john.salary = 1000

The functional equivalent of doing class.attribute is to use getattr(class, 'attribute'):
>>> class A:
... def __init__(self, a):
... self.a = a
...
>>> obj = A(1)
>>> obj.a
1
>>> getattr(obj, 'a')
1
>>>
From the documentation:
getattr(object, name[, default])
Return the value of the named attribute of object. name must be a string. If the string is the name of one of the object’s
attributes, the result is the value of that attribute. For example,
getattr(x, 'foobar') is equivalent to x.foobar. If the named
attribute does not exist, default is returned if provided, otherwise
AttributeError is raised.

Related

Dynamically add method to class from property function?

I think a code sample will better speak for itself:
class SomeClass:
example = create_get_method()
Yes, that's all – ideally.
In that case, create_get_method would add a get_example() to SomeClass in a way that it can be accessed via an instance of SomeClass:
obj = SomeClass()
obj.get_example() <- returns the value of self.example
(Of course, the idea is to implement a complex version of get_contact, that's why I want to do that in a non-repetitive way, and this is a simplified version that represents well the issue.)
I don't know if that's possible, because it require to have access to the property name (example) and the class (SomeClass) since these can not be guessed in advance (that function will be used on many and various classes).
I know it's something possible, because that's kind of what SQLAlchemy does with their relationship() function on a class:
class Model(BaseModel):
id = ...
contact_id = db.Integer(db.ForeignKey..)
contact = relationship('contact') <-- This !
How can this be done?
Objects bound to class-level variables can have a __set_name__ method that will be called immediately after the class object has been created. It will be called with two arguments, the class object, and the name of the variable the object is saved as in the class.
You could use this to create your extra getter method, though I'm not sure why exactly you want to (you could make the object a descriptor instead, which would probably be better than adding a separate getter function to the parent class).
class create_get_method:
def __set_name__(self, owner, name):
def getter(self):
return getattr(self, name)
getter_name = f"get_{name}"
getter.__name__ = getter_name
setattr(owner, getter_name, getter)
# you might also want a __get__ method here to give a default value (like None)
Here's how that would work:
>>> class Test:
... example = create_get_method()
...
>>> t = Test()
>>> print(t.get_example())
<__main__.create_get_method at 0x000001E0B4D41400>
>>> t.example = "foo"
>>> print(t.get_example())
foo
You could change the value returned by default (in the first print call), so that the create_get_method object isn't as exposed. Just add a __get__ method to the create_get_method class.
You can do this with a custom non-data descriptor, like a property, except that you don't need a __set__ method:
class ComplicatedDescriptor:
def __init__(self, name):
self.name = name
def __get__(self, owner, type):
# Here, `owner` is the instance of `SomeClass` that contains this descriptor
# Use `owner` to do some complicated stuff, like DB lookup or whatever
name = f'_{self.name}'
# These two lines for demo only
value = owner.__dict__.get(name, 0)
value += 1
setattr(owner, name, value)
return value
Now you can have any number of classes that use this descriptor:
class SomeClass:
example = ComplicatedDescriptor('example')
Now you can do something like:
>>> inst0 = SomeClass()
>>> inst1 = SomeClass()
>>> inst0.example
1
>>> inst1.example
1
>>> inst1.example
2
>>> inst0.example
2
The line name = f'_{self.name} is necessary because the descriptor here is a non-data descriptor: it has no __set__ method, so if you create inst0.__dict__['example'], the lookup will no longer happen: inst0.example will return inst0.__dict__['example'] instead of calling SomeClass.example.__get__(inst0, type(inst0)). One workaround is to store the value under the attribute name _example. The other is to make your descriptor into a data descriptor:
class ComplicatedDescriptor_v2:
def __init__(self, name):
self.name = name
def __get__(self, owner, type):
# Here, `owner` is the instance of `SomeClass` that contains this descriptor
# Use `owner` to do some complicated stuff, like DB lookup or whatever
# These two lines for demo only
value = owner.__dict__.get(self.name, 0)
value += 1
owner.__dict__[self.name] = value
return value
def __set__(self, *args):
raise AttributeError(f'{self.name} is a read-only attribute')
The usage is generally identical:
class SomeClass:
example = ComplicatedDescriptor_v2('example')
Except that now you can't accidentally override your attribute:
>>> inst = SomeClass()
>>> inst.example
1
>>> inst.example
2
>>> inst.example = 0
AttributeError: example is a read-only attribute
Descriptors are a fairly idiomatic way to get and set values in python. They are preferred to getters and setters in almost all cases. The simplest cases are handled by the built-in property. That being said, if you wanted to explicitly have a getter method, I would recommend doing something very similar, but just returning a method instead of calling __get__ directly.
For example:
def __get__(self, owner, type):
def enclosed():
# Use `owner` to do some complicated stuff, like DB lookup or whatever
name = f'_{self.name}'
# These two lines for demo only
value = owner.__dict__.get(name, 0)
value += 1
setattr(owner, name, value)
return value
return enclosed
There is really no point to doing something like this unless you plan on really just want to be able to call inst.example().

How to assign a value to the class attribute corresponding to the value of a specific string variable? [duplicate]

How do you set/get the values of attributes of t given by x?
class Test:
def __init__(self):
self.attr1 = 1
self.attr2 = 2
t = Test()
x = "attr1"
There are built-in functions called getattr and setattr
getattr(object, attrname)
setattr(object, attrname, value)
In this case
x = getattr(t, 'attr1')
setattr(t, 'attr1', 21)
If you want to keep the logic hidden inside the class, you may prefer to use a generalized getter method like so:
class Test:
def __init__(self):
self.attr1 = 1
self.attr2 = 2
def get(self,varname):
return getattr(self,varname)
t = Test()
x = "attr1"
print ("Attribute value of {0} is {1}".format(x, t.get(x)))
Outputs:
Attribute value of attr1 is 1
Another apporach that could hide it even better would be using the magic method __getattribute__, but I kept getting an endless loop which I was unable to resolve when trying to get retrieve the attribute value inside that method.
Also note that you can alternatively use vars(). In the above example, you could exchange getattr(self,varname) by return vars(self)[varname], but getattrmight be preferable according to the answer to What is the difference between vars and setattr?.
Note: This answer is very outdated. It applies to Python 2 using the new module that was deprecated in 2008.
There is python built in functions setattr and getattr. Which can used to set and get the attribute of an class.
A brief example:
>>> from new import classobj
>>> obj = classobj('Test', (object,), {'attr1': int, 'attr2': int}) # Just created a class
>>> setattr(obj, 'attr1', 10)
>>> setattr(obj, 'attr2', 20)
>>> getattr(obj, 'attr1')
10
>>> getattr(obj, 'attr2')
20

When and why to use self.__dict__ instead of self.variable

I'm trying to understand some code which is using this class below:
class Base(object):
def __init__(self, **kwargs):
self.client = kwargs.get('client')
self.request = kwargs.get('request')
...
def to_dict(self):
data = dict()
for key in iter(self.__dict__): # <------------------------ this
if key in ('client', 'request'):
continue
value = self.__dict__[key]
if value is not None:
if hasattr(value, 'to_dict'):
data[key] = value.to_dict()
else:
data[key] = value
return data
I understand that it gets keyword arguments passed to the Base class like for example, Base(client="foo", request="bar").
My confusion is, why is it using self.__dict__ which turns variables inside __init__ to a dict (e.g {"client": "foo", "request": "bar"}) instead of just calling them by self.client & self.request inside other methods? When and why I should use self.__dict__ instead?
Almost all of the time, you shouldn't use self.__dict__.
If you're accessing an attribute like self.client, i.e. the attribute name is known and fixed, then the only difference between that and self.__dict__['client'] is that the latter won't look up the attribute on the class if it's missing on the instance. There is very rarely any reason to do this, but the difference is demonstrated below:
>>> class A:
... b = 3 # class attribute, not an instance attribute
...
>>> A.b # the class has this attribute
3
>>> a = A()
>>> a.b # the instance doesn't have this attribute, fallback to the class
3
>>> a.__dict__['b'] # the instance doesn't have this attribute, but no fallback
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'b'
The main use-case for self.__dict__ is when you don't want to access a fixed, known attribute name. In almost all code, you always know which attribute you want to access; and if you do need to look something up dynamically using an unknown string, you should create a dictionary yourself, and write self.that_dict[key] instead of self.__dict__[key].
So the only times you should really use __dict__ is when you are writing code which needs to work regardless of which attributes the instance might have; i.e. you specifically want code which will work even if you change the class's structure or its attribute names, or code which will work across multiple classes with different structures. I'll show one example below.
The __repr__ method
The __repr__ method is meant to return a string representing the instance, for the programmer's convenience when using a REPL. For debugging/testing purposes this string usually contains information about the object's state. Here's a common way to implement it:
class Foo:
def __init__(self, foo, bar, baz):
self.foo = foo
self.bar = bar
self.baz = baz
def __repr__(self):
return 'Foo({!r}, {!r}, {!r})'.format(self.foo, self.bar, self.baz)
This means if you write obj = Foo(1, 'y', True) to create an instance, then repr(obj) will be the string "Foo(1, 'y', True)", which is convenient because it shows the instance's entire state, and also the string itself is Python code which creates an instance with the same state.
But there are a few issues with the above implementation: we have to change it if the class's attributes change, it won't give useful results for instances of subclasses, and we have to write lots of similar code for different classes with different attributes. If we use __dict__ instead, we can solve all of those problems:
def __repr__(self):
return '{}({})'.format(
self.__class__.__name__,
', '.join('{}={!r}'.format(k, v) for k, v in self.__dict__.items())
)
Now repr(obj) will be Foo(foo=1, bar='y', baz=True), which also shows the instance's entire state, and is also executable Python code. This generalised __repr__ method will still work if the structure of Foo changes, it can be shared between multiple classes via inheritance, and it returns executable Python code for any class whose attributes are accepted as keyword arguments by __init__.
__dict__ holds all of the variables in the class. Take the following class:
class A():
def __init__(self, foo):
self.foo = foo
def new_var(self, bar):
self.bar = bar
Then in this case, notice:
a = A('var1')
print(a.__dict__) # {'foo': 'var1'}
b = A('var1')
b.new_var('var2')
b.foobar = 'var3'
print(b.__dict__) # {'foo': 'var1', 'bar': 'var2', 'foobar': 'var3'}
In your case you could do either or. __dict__ is a great way to grab all of the variables that are part of that class at the current instance in which it is called. You can check out the documentation on __dict__ here.
__dict__ is used when checking what instance variables(data attributes) an object has.
So, if there is Person class below:
class Person:
x1 = "Hello"
x2 = "World"
def __init__(self, name, age):
self.name = name
self.age = age
def test1(self):
print(self.__dict__) # Here
#classmethod
def test2(cls):
pass
#staticmethod
def test3():
pass
obj = Person("John", 27)
obj.test1() # Here
__dict__ gets name and age with their values in a dictionary as shown below:
{'name': 'John', 'age': 27} # Here
And, if the new instance variable gender is added after instanciation as shown below:
# ...
obj= Person("John", 27)
obj.test1()
obj.gender = "Male" # Here
obj.test1()
__dict__ gets name, age and gender with their values in a dictionary as shown below:
{'name': 'John', 'age': 27}
{'name': 'John', 'age': 27, 'gender': 'Male'} # Here

behaviour of descriptor concept in python (confusing)

I understood python descriptor but I have a little confusion about this..
if you have a class descriptor as follows
class Descriptor(object):
def __get__(self, instance, owner):
print 'getting'
return self.value
def __set__(self, instance, value):
print 'setting'
self.value = value
def __delete__(self, instance):
print 'deleting'
del self.value
and a class whose attributes we want to manage is something like this..
class Test(object):
name = Descriptor()
def __init__(self, name):
print 'init test'
self.name = name
when I create object of class Test and do something it gives me answer like this...
t = Test('abc')
init test
setting
>>> t.name
getting
'abc'
>>> del t.name
deleting
>>> t
<__main__.Test object at 0x013FCCD0>
>>> t.name
getting
Now I want to have a class Test1 something like this..
class Test1(object):
def __init__(self, value):
print 'init test1'
self.name = Descriptor()
self. value = value
and if I create object of Test1 and try to access attribute of instance of Test1, I get output something like this..
t1 = Test1(12)
t1.name
>>> getting
>>> 12
>>> t1.name = 30
>>> setting
Q 1) my question is that is this name attribute declared in init of Test1, is bound to instance of Test1 or not... because when I try to get attribute dictionary of t1, it return empty dict...
t1.__dict__
>>> {}
same for class Test's instance t
t.__dict__
>>> {}
When I add a new attribute to any of these instances, like this...
t.some = 'some'
>>> t1.some = 'some'
and again if I try to access attribute dictionary it gives me only which I have added just now.. now all instance attribute
t.__dict__
>>> {'some': 'some'}
>>> t1.__dict__
>>> {'some': 'some'}
Q 2) So what is the difference between instance attributes defined in init (like variable name and value in class Descriptor and Test) and attributes defined after instance creation (like variable t.some).
Q 3) How class Test is different than class Test1.
In Test1 your Descriptor isn't really used as a descriptor, it's just a normal attribute called name, that happens to have some the special methods. But that doensn't really make it a descriptor yet.
If you read the docs about how descriptors are invoked, youll see the mechanism that is used to invoke the descriptors methods. In your case this would mean t.name woud be roughly equivalent to:
type(t).__dict__['name'].__get__(t, type(t))
and t1.name:
type(t1).__dict__['name'].__get__(t1, type(t1))
name is looked up in the __dict__ of the class, not of the instance, so that's where the difference is, Test1.__dict__ doesn't have a descriptor called name:
>>> Test.__dict__['name']
<__main__.Descriptor object at 0x7f637a57bc90>
>>> Test1.__dict__['name']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'name'
What you also should consider, is that your descriptor sets the value attribute on itself, that means all instances of Test will share the same value:
>>> t1 = Test(1)
init test
setting
>>> t2 = Test(2)
init test
setting
>>> t1.name
getting
2
>>> t2.name
getting
2
>>> t1.name = 0
setting
>>> t2.name
getting
0
I think that what yo acutally want to do is to set value on instance instead of self, that would get you the expected behaviour in Test.

Built-in function to read __slots__

Let's say I have a class like this:
class Test(object):
prop = property(lambda self: "property")
The descriptor takes priority whenever I try to access Test().prop. So that will return 'property'. If I want to access the object's instance storage, I can do:
x = Test()
x.__dict__["prop"] = 12
print(x.__dict__["prop"])
However if I change my class to:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
How do I do the same, and access the internal storage of x, to write 12 and read it back, since x.__dict__ no longer exist?
I am fairly new with Python, but I understand the Python philosophy is to give complete control, so why is an implementation detail preventing me from doing that?
Isn't Python missing a built-in function that could read from an instance internal storage, something like:
instance_vars(x)["prop"] = 12
print(instance_vars(x)["prop"])
which would work like vars, except it also works with __slots__, and with built-in types that don't have a __dict__?
Short answer, You can't
The problem is that slots are themselves implemented in terms of descriptors. Given:
class Test(object):
__slots__ = ("prop",)
t = Test()
the phrase:
t.prop
Is translated, approximately to:
Test.prop.__get__(t, Test)
where Test.prop is a <type 'member_descriptor'> crafted by the run-time specifically to load prop values out of Test instances from their reserved space.
If you add another descriptor to the class body definition, it masks out the member_descriptor that would let you get to the slotted attribute; there's no way to ask for it, it's just not there anymore. It's effectively like saying:
class Test(object):
#property
def prop(self):
return self.__dict__['prop']
#property
def prop(self):
return "property"
You've defined it twice. there's no way to "get at" the first prop definition.
but:
Long answer, you can't in a general way. You can
You can still abuse the python type system to get at it using another class definition. You can change the type of a python object, so long as it has the exact same class layout, which roughly means that it has all of the same slots:
>>> class Test1(object):
... __slots__ = ["prop"]
... prop = property(lambda self: "property")
...
>>> class Test2(object):
... __slots__ = ["prop"]
...
>>> t = Test1()
>>> t.prop
'property'
>>> t.__class__ = Test2
>>> t.prop = 5
>>> t.prop
5
>>> t.__class__ = Test1
>>> t.prop
'property'
But there's no general way to introspect an instance to work out its class layout; you just have to know from context. You could look at it's __slots__ class attribute, but that won't tell you about the slots provided in the superclass (if any) nor will it give you any hint if that attribute has changed for some reason after the class was defined.
I don't quite understand what and why you want to do this, but does this help you?
>>> class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
>>> a = Test()
>>> b = Test()
>>> a.prop
'property'
>>> tmp = Test.prop
>>> Test.prop = 23
>>> a.prop
23
>>> Test.prop = tmp; del tmp
>>> b.prop
'property'
of course, you cannot overwrite the property on a per-instance basis, that's the whole point of slotted descriptors.
Note that subclasses of a class with __slots__ do have a __dict__ unless you manually define __slots__, so you can do:
>>> class Test2(Test):pass
>>> t = Test2()
>>> t.prop
'property'
>>> t.__dict__['prop'] = 5
>>> t.__dict__['prop']
5
>>> Test2.prop
<property object at 0x00000000032C4278>
but still:
>>> t.prop
'property'
and that's not because of __slots__, it's the way descriptors work.
your __dict__ is bypassed on attribute lookup, you are just abusing it as data structure that happens to be there for storing a state.
it is equivalent to do this:
>>> class Test(object):
__slots__ = ("prop", "state")
prop = property(lambda self: "property")
state = {"prop": prop}
>>> t.prop
'property'
>>> t.state["prop"] = 5
>>> t.state["prop"]
5
>>> t.prop
'property'
If you really ever want to do something like that, and you REALL REALLY need something like that, you can always override __getattribute__ and __setattribute__, it's just as stupid... This is just to prove it to you:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
__internal__ = {}
def __getattribute__(self, k):
if k == "__dict__":
return self.__internal__
else:
try:
return object.__getattribute__(self, k)
except AttributeError, e:
try:
return self.__internal__[k]
except KeyError:
raise e
def __setattribute__(self, k, v):
self.__internal__[k] = v
object.__setattribute__(self, k, v)
t = Test()
print t.prop
t.__dict__["prop"] = "test"
print "from dict", t.__dict__["prop"]
print "from getattr", t.prop
import traceback
# These won't work: raise AttributeError
try:
t.prop2 = "something"
except AttributeError:
print "see? I told you!"
traceback.print_exc()
try:
print t.prop2
except AttributeError:
print "Haha! Again!"
traceback.print_exc()
(Tried it on Python 2.7)
It's exactly what you expect I guess. Don't do this, it's useless.

Categories

Resources