Python - Use variable to call object [duplicate] - python

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 6 years ago.
I am trying to call an object from a variable. I know how to use getattr to call a function of an object using a variable but can't work out how to use a variable to define the object name. I have dragged some example code below:
class my_class(object):
def __init__(self, var):
self.var1 = var
var = "hello"
object_1 = my_class(var)
print object_1.var1 # outputs - hello
attribute = "var1"
# i can call the attribute from a variable
print getattr(object_1, attribute) # outputs - hello
object = "object_1"
# but i do not know how to use the variable "object" defined above to call the attribute
# now i have defined the variables object and attribute how can i use them to output "hello"?

Since object_1 and object are global variables, you may use the code below:
print(globals()[globals()['object']].var1) # "hello" is printed
or this:
print(getattr(globals()[globals()['object']], attribute)) # "hello" is printed
where
globals()['object'] represents "object_1" string
globals()[globals()['object']] represents object_1 object.

Related

How can I create classes with different class attributes within a function? [duplicate]

This question already has answers here:
Creating a class within a function and access a function defined in the containing function's scope [duplicate]
(2 answers)
Closed 2 years ago.
I would like to have a function that allows generating classes with custom class attributes. Like so:
def test_factory(a):
class Test:
a = a
return Test
However, when I try to call test_factory, I get an error:
test_factory(1)
> NameError: name 'a' is not defined
The expected behaviour would be:
t1 = test_factory(1)
t2 = test_factory(2)
print(t1.a, t2.a)
> 1, 2
How can I create classes that differ in their class attributes by calling a function?
You have to rename the function argument to not collide with the name of the class attribute:
def test_factory(b):
class Test:
a = b
return Test
>>> t1 = test_factory(1)
>>> t2 = test_factory(2)
>>> print(t1.a, t2.a)
1 2
When parsing the class statement, the assignment to a defines it as part of the temporary class namespace, similar to an assignment to a local variable in a function definition. As such, the name a then shadows the name of the parameter in the enclosing function scope.
You can either change the parameter name (as shown by schwobaseggl)
def test_factory(a_value):
class Test:
a = a_value
return Test
or set the attribute after the definition:
def test_factory(a):
class Test:
pass
Test.a = a
return Test
or call type directly:
def test_factory(a):
return type('Test', (), {'a': a})

__call__ behavior [duplicate]

This question already has answers here:
What is the difference between __init__ and __call__?
(17 answers)
Closed 3 years ago.
I don't understand the behavior of __call__:
class Filter:
def __init__(self, before, after, source):
self.filter = {}
self.filter['before:'] = before
self.filter['after:'] = after
self.filter['source:'] = source
def __call__(self):
return ' AND '.join([key + value for key, value in self.filter.items()])
When I call the instance, __call__ is not executed:
print(Filter(before='today', after='yesterday', source='web'))
returns <__main__.Filter object at 0x103f2bf10>
while
print(Filter(before='today', after='yesterday', source='web').__call__())
does what I want and returns what is defined in __call__(): before:today AND after:yesterday AND source:web
Why is this happening? Do I need to create an empty object first, then instantiate it, to make __call__ work?
In Filter(before='today', after='yesterday', source='web'), you don't call an instance, you create one. When you print it, you get the default representation for an instance of class Filter: <__main__.Filter object at 0x103f2bf10>
You need to create the instance first, then call it:
filter = Filter(before='today', after='yesterday', source='web')
filter()
Output:
'before:today AND after:yesterday AND source:web'
There is no need to explicitely use <your instance>.__call__(), just use the parentheses like you would do for any function.
Filter(...) does not "call" the instance, it creates it. To call, use the call syntax on the resulting object:
>>> Filter(...)()
or
>>> filt = Filter(...)
>>> filt()

Have a Function Take a Variable Name of an Object [duplicate]

This question already has answers here:
How to access (get or set) object attribute given string corresponding to name of that attribute
(3 answers)
Closed 4 years ago.
If I have the following code:
class foo:
def __init__(self):
self.w = 5
self.z = 10
def sum(obj,x,y):
return obj.x+obj.y
f = foo()
print sum(foo,'x','y')
How would I create a function that takes in two unkown variable names and returns the sum of those variables variables?
In this case the example should print 15.
EDIT:
Typo for the last line it should say print sum(foo,'w','z')
All (I think?) python objects have a built-in __getattribute__ method. Use it like this:
def sum(obj,x,y):
return obj.__getattribute__(x)+obj.__getattribute__(y)
The method takes a string, and "unpacks" it to being a variable name.

When defining class method, why there an equals sign in argument e.g. func(foo=3) [duplicate]

This question already has answers here:
What does ** (double star/asterisk) and * (star/asterisk) do for parameters?
(25 answers)
Closed 5 years ago.
I'm learning python, trying to figure out how does this code actually work:
def func(**args):
class BindArgs(object):
foo = args['foo']
print 'foo is ', foo
def __init__(self,args):
print "hello i am here"
return BindArgs(args) #return an instance of the class
f = func(foo=2)
Output:
foo is 2
hello i am here
But it's very confused that in the argument of a function func(foo=2) that takes equation mark in it. Could you please explain how the flow works?
Here is an abstract:
You call the function func and pass a dictionary as the argument to it.
In the func function, you define a class named BindArgs, and then in the return statement, you first make an object (instance) from the BindArgs class and then return that instance.
Notice that the statement foo = args['foo'] get the key value of 'foo' from the args dictionary (that is 2 in your sample code).
the init also will be run as the constructor of the class when you are creating an object.

Reference objects for accessing members [duplicate]

This question already has answers here:
How do I pass a variable by reference?
(39 answers)
Closed 5 years ago.
I would like to change the value of a member of an object. I can do this as long as i adress the object itself. However when I store a reference to this member it doesn't work. Instead it changes the reference object.
class MyClass:
def __init__(self, name):
self.a = 1
self.b = name
obj1=MyClass("string")
refob1=obj1.a
refob2=obj1.b
#I can change my object like this:
obj1.a=99
obj2.b="changed"
#But not like this:
refob1 = 1
refob2 = "changed_reference"
How can I use the reference object to change the members?
This is because int and strings in python are non-mutable objects. This means that they pass a copy of the value instead of the reference.
lists, in the other hand, are mutable objects and allow your desired behavior. Here you have an example:
class MyClass(object):
def __init__(self):
self.a = 3
self.b = [1]
obj = MyClass()
outside_a = obj.a
outside_a = 3 # outside_a is just a copy of obj.a value, so it won't change obj object
outisde_b = obj.b
outside_b[0] = 3 # Lists are mutabe, so this will change obj.b value
print obj.b # Prints [3]
So, how can you go around this? It is a bit ugly, but you can use a container (list) to contain the variables you want to reference later on. Here you can find a related post: Python passing an integer by reference

Categories