Setting name of variable in a class with a function? - python

I have a class and I want to do something like the following:
class my_class:
def my_func(self, var_name):
self.var_name = 5
a = my_class()
a.my_func('yes')
print(a.yes)
I am not sure how to set the class variable name using the function however

>>> class my_class(object):
... def my_func(self,var_name):
... setattr(self,var_name,5)
...
>>> a = my_class()
>>> a.my_func('yes')
>>> a.yes
5

Related

Calling variable inside self parameter in class method

I wonder if we can call variable initiated in self in class method. For example:
class ABC():
def method1(self):
self.var1 = '123'
#classmethod
def callvar1(cls):
'''print var1'''
I want to achieve the same output like this:
class ABC():
var1 = '123'
def method1(self):
self.var1 = '123'
#classmethod
def callvar1(cls):
print(cls.var1)
How can I access self.var1 in callvar1?
Since callvar1 is a class method, it does not have access to self. This is because the method is not tied to a specific instance of the class, but rather to the class itself. Therefore, when you call the method, it does not know which instance you are referring to. As you did in the second block of the code, you must pass the object whose var1 you would like to print to the function.
Your other option would be to not make it a class method.
Class methods are bound to the class itself rather than a particular instance of it so if you're trying to access self.var1 (an instance variable) inside the class method you're not going to have much fun.
Your best option is to simply make the method not a class method (depending on your use case):
>>> class ABC():
... var1 = '123'
... def method1(self):
... self.var1 = '123'
... def callvar1(self):
... print(self.var1)
...
>>> b = ABC()
>>> b.callvar1()
123
Although another option is to pass an instance of the class to the class method:
>>> class ABC():
... var1 = '123'
... def method1(self):
... self.var1 = '123'
... #classmethod
... def callvar1(cls, inst):
... print(inst.var1)
...
>>> b = ABC()
>>> ABC.callvar1(b)
123
Use the self keyword to access members of the class.
class ABC():
var1 = '123'
def method1(self):
self.var1 = '123'
#classmethod
def callvar1(self):
print(self.var1)

Influencing class variables with functions that are method's variables

Say I have a class with a method that takes a function as an argument. Is there any way to make this function change inclass variables?
def f():
# something here to change MyClass.var
class MyClass:
def __init__():
self.var = 1
def method(self, func):
#does something
func()
obj = MyClass()
obj.method(f)
print(obj.var)
Simply pass the internal reference of your class - self - into the function:
>>> class Class:
def __init__(self):
self.var = 1
def method(self, func):
func(self)
>>> def func(inst):
inst.var = 0
>>> cls = Class()
>>> cls.var
1
>>> cls.method(func)
>>> cls.var
0
>>>
On a related side note, I'd argue that it'd be cleaner and clearer to actually make your function a method of your class:
>>> from types import MethodType
>>>
>>> def func(self):
self.var = 0
>>> class Class:
def __init__(self):
self.var = 1
>>> cls = Class()
>>> cls.var
1
>>> cls.func = MethodType(func, cls)
>>> cls.func()
>>> cls.var
0
>>>
This should work:
def f(obj):
obj.var = 2
class MyClass:
def __init__(self):
self.var = 1
def method(self, func):
# does something
func(self)
obj = MyClass()
obj.method(f)
print(obj.var) # --> 2
Since the function f is defined outside the scope of the class, it can not access the class variable. However you can pass the class variable as an argument to f, and in that case it will be able to do any operation on it.
def f(x):
return x**2 # just for the demonstration. Will square the existing value\\
# of the class variable
class MyClass:
def __init__(self):
self.var = 2
def method(self, func):
#does something
self.var = func(self.var)
obj = MyClass()
obj.method(f)
print(obj.var)
>>> 4

Is it possible to extract values from namespace to class?

For example values from args i can extract like this
globals().update(vars(args))
Is it possible automatically create same properties fro class? Something like this
class SomeClass():
def __init__(self, args):
globals().update(vars(args))
exit(self.location)
I think you meant you want to update the attributes on the class; you can do so with:
class SomeClass():
def __init__(self, args):
vars(self).update(vars(args))
Demo:
>>> class Foo:
... def __init__(self):
... self.bar = 'baz'
...
>>> result = SomeClass(Foo())
>>> result.bar
'baz'

How to define similar class-functions related to different class-properties inside __init__

I have a class like this:
class MyClass(object):
def f_1(self,x):
return foo(x, self.property_1)
def f_2(self,x):
return foo(x, self.property_2)
The idea is that multiple functions f_n have a common structure, but depend on different properties property_n of the class.
I look for a more compact way to define those f_n in the __init__? I think of something like
class MyClass(object):
def __init__(self):
self.f_1 = self.construct_function(self.property_1)
self.f_2 = self.construct_function(self.property_2)
def construct_function(self, property):
# ???
That is what I have in mind, but I dont know how to define this construct_function. It is important that 'property' is of a point-by-value type.
Edit:
I simplified Martijn's very good answer to this solution, which works fine:
def construct_function(property_name):
def f_n(self, x):
return foo(x, getattr(self, property_name))
return f_n
class MyClass2(object):
f_1 = construct_function('property_1')
f_2 = construct_function('property_2')
Just wanted to mention it here, as multiline comments are not allowed...
If you want to generate these methods per class, use a class decorator:
def property_functions(**properties):
def construct_method(prop):
def f_n(self):
return foo(getattr(self, prop))
return f_n
def class_decorator(cls):
for name, prop in properties.iteritems():
setattr(cls, name, construct_method(prop))
return cls
return class_decorator
then use it like:
#property_functions(f_1='property_1', f_2='property_2')
class MyClass(object):
property_1 = 'foo'
property_2 = 'bar'
Demonstration:
>>> def foo(value): print value
...
>>> #property_functions(f_1='property_1', f_2='property_2')
... class MyClass(object):
... property_1 = 'foo'
... property_2 = 'bar'
...
>>> mc = MyClass()
>>> mc.f_1()
foo
>>> mc.f_2()
bar
You can have a look at getattr or getattribute . They allow you dynamically create and reference attributes. For ex
It works something like this:
class foo:
def __init__(self):
self.a = "a"
def __getattr__(self, attribute):
return "You asked for %s, but I'm giving you default" % attribute
>>> bar = foo()
>>> bar.a
'a'
>>> bar.b
"You asked for b, but I'm giving you default"
>>> getattr(bar, "a")
'a'
>>> getattr(bar, "b")
"You asked for b, but I'm giving you default"

python oop polymorphism

I can't understand why this code:
class A(object):
def __init__(self):
self.__value = 1
def get_value(self):
return self.__value
class B(A):
def __init__(self):
A.__init__( self )
self.__value = 2
b = B()
print b.get_value()
gives 1, but not 2. Thanks for your help.
Your problem is that double underscores are special in python, and create some modicum of privacy (not enforced, but it mangles the names, which is what is affecting you here). You should recreate this without the variable being named with double underscores. Also, you should use super instead of calling A.__init__ explicitly:
>>> class A(object):
... def __init__(self):
... self.value = 1
... def get_value(self):
... return self.value
...
>>> class B(A):
... def __init__(self):
... super(B, self).__init__()
... self.value = 2
...
>>> b = B()
>>> b.get_value()
2
For more specifics if you don't want to read the referenced documentation:
If you read the link on "special" above, that paragraph describes the internal name mangling that happens when you use __. The short answer is that A.get_value() returns _A__value, and setting self.__value in B actually sets a member variable named _B__value, which means that A.get_value() never sees it.
You can prove this to yourself by indeed doing something truly hinky:
>>> class A(object):
... def get_value(self):
... return self._B__value
...
>>> class B(A):
... def __init__(self):
... self.__value = 2
...
>>> b = B()
>>> b.get_value()
2
self.__value = 1 creates 'private' field, which is invisible for children in a such way.
Use single underscore for 'protected' fields.
E.g. self._value = 1
When you creates field with name started with double underscore, Python makes some modification on it before adding to object's __dict__:
>>> class A(object):
... def __init__(self):
... self.__value = 1
... def get_value(self):
... return self.__value
...
>>> A().__dict__
{'_A__value': 1}
That is why __value field is not visible in child object.

Categories