Getting variables within the __init__ def in python in some class - python

I have a class with certain inside variables in it, let's take a simple example
class Example:
def __init__(self):
self.variable = "something"
self.anotherVariable = "somethingElse"
Now the signature in "inspect" only provides me with what's in the brackets, which in this case only the self, but can I somehow get a list of variable names within the class, so if I run that code it will result in:
Output:
(self.variable, self.anotherVariable)
I appreciate all the help :)

I don't think you need inspect:
class Example:
def __init__(self):
self.variable = "something"
self.anotherVariable = "somethingElse"
print(Example.__init__.__code__.co_names)
Output:
('variable', 'anotherVariable')

Another way is like this; invoking dir on object itself:
class Example:
def __init__(self):
self.variable = 1
self.anotherVariable = 2
obj = Example()
print([attrib for attrib in dir(obj) if not attrib.startswith("_")])
O/P
['variable', 'anotherVariable']

There are a few ways to do this I prefer __dict__.
This is built into every class you make unless you override it. Since we’re dealing with a Python dictionary, we can just call its keys method.
Here is an example.
class Example:
def __init__(self):
self.variable = "something"
self.anotherVariable = "somethingElse"
obj = Example()
variables = obj.__dict__.keys()
Output --> ['varTwo', 'varThree', 'varOne']
Hope this helps. There are also few other methods you can check out here :
http://www.blog.pythonlibrary.org/2013/01/11/how-to-get-a-list-of-class-attributes/

Related

Python - Class object as function argument: Object only - Class not in argument

I am trying to write a function taking a string as an argument and using this argument as a class object.
Note that my explanantion might be strangely formulated sice I could not find an answer online. The MWE below should clarify what I mean, the problematic line is indicated.
Edit: in the MWE, "print" is an example. I need to be able to call the object to update it, print it or, in the case of a list, append to it. I need access to the object itself, not the value of the object.
MWE
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Define function
def myFunction (parameter):
print(myObject.parameter)##### This line is currently not possible.
# Use class
myObject = myClass()
# Use function
myFunction("one")
I am not trying to append a new object to the class, only to call an existing object.
Is this even possible?
Looks like you need the built-in function called getattr
my_object = myClass()
def my_function(parameter):
print(getattr(my_object, parameter, None))
also this is not the best practice to call objects from outer scope like that. i'd suggest to use dict magic methods:
class MyClass:
def __init__(self):
self.one = "Test"
self.two = "Plop"
def __getitem__(self, parameter):
return getattr(self, parameter, None)
def __setitem__(self, parameter, value):
return setattr(self, parameter, value)
my_obj = MyClass()
parameter = "x"
print(my_obj[parameter])
my_obj[parameter] = "test"
print(my_obj.x)
You need to use getarttr():
# Create a class
class myClass():
def __init__(self):
self.one = "Test"
self.two = "Plop"
# Use class
myObject = myClass()
# Define function
def myFunction(parameter):
print(getattr(myObject, parameter))##### This line is currently possible.
# Use function
myFunction("one")

Pass attribute to class method

How can I pass class attribute to a class method so that the attribute will be modified?
class foo:
def __init__(self):
self.diamond = 1
self.gold = 10
self.change(self.diamond)
self.change(self.gold)
def change(self, x):
x+=1
model = foo()
print(model.diamond)
output:
1
I want diamond becomes 2.
Is this a good solution for you?
class foo:
def __init__(self):
self.diamond = 1
def change(self):
self.diamond += 1
model = foo()
model.change()
print(model.diamond)
Let me say this first that you have no class method, or class variable in your example. What you have are instance variables and instance methods, note the self keyword. Now, with that said, you can access and modify your instance variables from any instance method, just like #Almog answered earlier.
The x in your change method is a local variable, basically it's not available outside your method. As for how you modify a variable by passing it to a function, it's not doable with your code I think. You would need something like a dataclass, which you can modify. Check out 'PassByValue' and 'PassByReference' concepts relating to this. Maybe someone else here can help with your particular situation.

Calling class-specific method from another class

I am working in a class called AlgoSystem, which is given strategy_0 and strategy_1 as inputs under initialization as well as the number of strategies (2 in this case). The strategy classes are stored in a dictionary called "strategies" within the AlgoSystem. Both strategy_0 and strategy_1 are different classes themselves, but both with a function called "__on_tick". These functions I want to call from within the AlgoSystem class.
My current attempt to do this is seen below:
class AlgoSystem:
def __init__(self, strategy_0, strategy_1, numstrategies):
self.var= 1
self.strategies = {0 : strategy_0,
1 : strategy_1}
self.num_strategies = numstrategies
def start(self):
for i in range(self.num_strategies):
self.strategies[i].__on_tick(self.var)
class Strategy_zero:
def __init__(self, x):
self.x = x
def __on_tick(self, var):
self.x = self.x + var
print(self.x)
class Strategy_one:
def __init__(self, y):
self.y = y
def __on_tick(self, var):
self.y = self.y - var
print(self.y)
strategy_0 = Strategy_zero(2)
strategy_1 = Strategy_one(4)
num_strategies = 2
system = AlgoSystem(strategy_0, strategy_1, 2)
system.start()
When I run the code above, I am given the error:
Strategy_zero' object has no attribute '_AlgoSystem__on_tick'
Apparently I'm not calling the class-functions "__on_tick" properly. How should I do this? I need to do it in a way, so I keep track on the changes of the two sub-classes (strategy_0 and strategy_1) through my defined dictionary within AlgoSystem: "strategies".
The double underscore prefix is specifically designed to prevent you from doing exactly what you are doing.
There is no reason for you to use it here. Remove the prefix and can your methods just on_tick.
Double underscore names are hidden names (hidden by obfuscation). I suggest having your on_tick method be called on_tick and try again.
The following code might help clarify what's going on with name-mangling.
class A:
def __mangled(self):
print "Class A name-mangled method"
class B:
def __init__(self):
a = A()
try:
a.__mangled()
except AttributeError:
# an attempt to access a name-mangled method assumes that
# the '_{class_name}' prefix should use 'B' as the class name
print "A instance has no attribute '_B__mangled'"
a._A__mangled()
# prints "Class A name-mangled method"
getattr(a, '_{}__mangled'.format(a.__class__.__name__))()
# same thing, but can be done without knowing the class name
B()
So, you could update self.strategies[i].__on_tick(self.var) to be:
strat = self.strategies[i]
getattr(strat, '_{}__on_tick'.format(strat.__class__.__name__)(self.var)
But, it would probably be best to not precede __on_tick with a double-underscore since it is intended to be accessed outside the class/instance.

How to use derived class variable in baseclass method

I have a hierarchy of classes that inherit from each other that look something like that:
class BaseClass(object):
def __init__(self):
self.localLog = logging.getLogger(testName)
self.var1 = 'a'
def printVar(self):
print self.var1
class SubClass1(BaseClass):
def __init__(self):
self.var1 = 'b'
super(SubClass1, self).__init__()
class SubClass2(SubClass1):
def __init__(self):
self.var1 = 'c'
super(SubClass2, self).__init__()
Now I want to instantiate SubClass2 and call BaseClass printVar method with SubClass2 local var1 variable:
obj = SubClass2()
obj.printVar()
What I want to happen is for variable c climb all the way up to the BaseClass and be passed to the printVar method. However, what I get is the variable a instead.
I realize that I will get the desired result by removing the super lines but I have to keep them to have access to the self.localLog variable in all inheriting classes.
Is there a way to achieve what I want or should I just keep a local printVar method for each class?
Seems like you can easily solve the problem simply by calling super(...).__init__() before setting var1 in your subclasses.

Python - naming an instance of a class with a var value

I'm trying to instantiate a class object whose desired name is held in a variable that's created elsewhere.
I can't figure out how to make the instance of the class have the name held by the variable.
example:
class foo:
def __init__(self):
self.var1 = "bar"
if __name__ == "__main__":
test = "a" # returned by another func.
[string held by variable 'test'] = foo()
print a.var1
Is this possible? (or even advisable...)
It is not advisable, since it makes it difficult to program with the variable a when you do not know its name until run-time.
You might think about using a dict instead:
data = {}
test = func() # "a"
data[test] = foo()
A function is probably better - that way the work you need to do is encapsulated and can be re-used:
def do_work(an_instance_of_foo):
print an_instance_of_foo.var1
class foo:
def __init__(self):
self.var1 = "bar"
if __name__ == "__main__":
do_work(foo())
If you also need the word, you can pass it to the function:
def do_work(an_instance_of_foo, my_word):
# etc.
Alternately, you can use a dictionary as a namespace (as #unutbu has suggested) if you need the instance of foo to be associated with a particular name.

Categories

Resources