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.
Related
I'd like to define a class inside a function (for testing purpose) and put a value into
a function variable:
def foo():
myvar = None
class myclass:
def run(self):
myvar = 5
mm = myclass()
mm.run()
print(myvar)
The above prints None
Is there any way other than global to make the myvar variable accessible from the class? The correct answer would print 5
It's not possible to assign a value to a variable outside the current scope without global. If you need to persist the value within the class you can define class variables instead. Example:
def foo():
class Class:
var_to_change = None
def run (self):
self.var_to_change = 5
print (Class.var_to_change)
instance = Class()
instance.run()
print (Class.var_to_change)
I haven't tested the above code but it should work in theory.
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/
I'm collecting instances using the following code:
class Hand():
instances = []
def __init__(self):
Hand.instances.append(self)
self.value = 5
def do_something(self, a):
self.value = self.value * a
class Foo():
def __init__(self):
pass
def insty(self):
self.hand1 = Hand()
self.hand2 = Hand()
foo = Foo()
foo.insty()
print Hand.instances
for hand in Hand.instances:
print "how do I print the instance name?"
The last line is just a way to learn how to to access the instance name so i can call the 'do_something' method on each instance in order.
How do I access the instance name for each instance of Hand?
If you mean how to get hand1 from the instance you assigned to self.hand1, the answer is that you can't. When you do self.hand1 = Hand(), you tell the Foo object it has a Hand, but the Hand object has no knowledge that it has been assigned to a Foo. You could do this:
h = Hand()
self.bob = h
self.larry = h
Now what is the "name" of that Hand supposed to be? You assigned the same hand to both "bob" and "larry", so there's no way it can have a single unique name.
If you want to have a name for each hand, you need to tell the hand what name you want to give it. You would have to modify your Hand code to allow you to pass a name to the constructor, then create the Hand with Hand("some name").
You can of course give the hands "names" by assigning attributes on them:
self.hand1 = Hand()
self.hand1.name = "hand 1"
. . . but these names are not special or "automatic" in any way.
The bottom line is that if you want something to have a name, you need to decide how to handle that name. You need write your own code that gives it its name, and your own code that retrieves its name.
I don't know if this would solve your problem or not. I needed to get instance names in order to do clear error reporting. Everywhere I looked, folks said "variables don't have names! The name is just a pointer to the thing!"
But it turns out that getting instance names in python is pretty straightforward.
Here's how I did it:
import gc
def instance_names(self):
referrers = gc.get_referrers(self)
result = []
dict_of_things = {}
for item in referrers:
if isinstance(item, dict):
dict_of_things = item
for k, v in dict_of_things.items():
if v == self:
result.append(k)
if not result:
result = ['unnamed instance']
return result
foo = Foo() means that the variable foo just points to the object returned by Foo(), there's no concept of name here.
foo.__dict__ will have "hand1" and "hand2" keys (among others). But you're probably going about this the wrong way. If the names are significant, you should use them as explicit indices in Foo (or somewhere).
e.g.
class Foo():
def __init__(self):
self.hands = {}
def insty(self):
self.hands['hand1'] = Hand()
self.hands['hand2'] = Hand()
I just started to learn Python and I"m struggling a little with instance variables. So I create an instance variable in a method that's of a list type. Later on, I want to call and display that variable's contents. However, I'm having issues doing that. I read some online, but I still can't get it to work. I was thinking of something along the following (this is a simplified version):
What would the proper way of doing this be?
class A:
def _init_(self):
self.listVar = [B("1","2","3"), B("1","2","3")]
def setListVal():
#Is this needed? Likewise a "get" method"?
def randomMethod():
A.listVar[0] #something like that to call/display it right? Or would a for
#for loop style command be needed?
Class B:
def _init_(self):
self.a = ""
self.b = ""
self.c = ""
Is the list something you'll be passing to the instance when you create it (i.e. will it be different each time)?
If so, try this:
class A:
def __init__(self, list):
self.listVar = list
Now, when you instantiate (read: create an instance) of a class, you can pass a list to it and it will be saved as the listVar attribute for that instance.
Example:
>>> first_list = [B("1","2","3"), B("1","2","3")]
>>> second_list = [C("1","2","3"), C("1","2","3")]
>>> first_instance = A(first_list) # Create your first instance and pass it your first_list. Assign it to variable first_instance
>>> first_instance.listVar # Ask for the listVar attribute of your first_instance
[B("1","2","3"), B("1","2","3")] # Receive the list you passed
>>> second_instance = A(second_list) # Create your second instance and pass it your second_list. Assign it to variable second_instance
>>> second_instance.listVar # Ask for the listVar attribute of your second_instance
[C("1","2","3"), C("1","2","3")] # Receive the list you passed second instance
Feel free to ask if anything is not clear.
class A:
def __init__(self):
self.listVar = [B("1","2","3"), B("1","2","3")]
def setListVal(self, val):
self.listVar[0] = val # example of changing the first entry
def randomMethod(self):
print self.listVar[0].a # prints 'a' from the first entry in the list
class B:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
I made several changes. You need to use self as the first argument to all the methods. That argument is the way that you reference all the instance variables. The initialization function is __init__ note that is 2 underscores before and after. You are passing three arguments to initialize B, so you need to have 3 arguments in addition to self.
I'm collecting instances using the following code:
class Hand():
instances = []
def __init__(self):
Hand.instances.append(self)
self.value = 5
def do_something(self, a):
self.value = self.value * a
class Foo():
def __init__(self):
pass
def insty(self):
self.hand1 = Hand()
self.hand2 = Hand()
foo = Foo()
foo.insty()
print Hand.instances
for hand in Hand.instances:
print "how do I print the instance name?"
The last line is just a way to learn how to to access the instance name so i can call the 'do_something' method on each instance in order.
How do I access the instance name for each instance of Hand?
If you mean how to get hand1 from the instance you assigned to self.hand1, the answer is that you can't. When you do self.hand1 = Hand(), you tell the Foo object it has a Hand, but the Hand object has no knowledge that it has been assigned to a Foo. You could do this:
h = Hand()
self.bob = h
self.larry = h
Now what is the "name" of that Hand supposed to be? You assigned the same hand to both "bob" and "larry", so there's no way it can have a single unique name.
If you want to have a name for each hand, you need to tell the hand what name you want to give it. You would have to modify your Hand code to allow you to pass a name to the constructor, then create the Hand with Hand("some name").
You can of course give the hands "names" by assigning attributes on them:
self.hand1 = Hand()
self.hand1.name = "hand 1"
. . . but these names are not special or "automatic" in any way.
The bottom line is that if you want something to have a name, you need to decide how to handle that name. You need write your own code that gives it its name, and your own code that retrieves its name.
I don't know if this would solve your problem or not. I needed to get instance names in order to do clear error reporting. Everywhere I looked, folks said "variables don't have names! The name is just a pointer to the thing!"
But it turns out that getting instance names in python is pretty straightforward.
Here's how I did it:
import gc
def instance_names(self):
referrers = gc.get_referrers(self)
result = []
dict_of_things = {}
for item in referrers:
if isinstance(item, dict):
dict_of_things = item
for k, v in dict_of_things.items():
if v == self:
result.append(k)
if not result:
result = ['unnamed instance']
return result
foo = Foo() means that the variable foo just points to the object returned by Foo(), there's no concept of name here.
foo.__dict__ will have "hand1" and "hand2" keys (among others). But you're probably going about this the wrong way. If the names are significant, you should use them as explicit indices in Foo (or somewhere).
e.g.
class Foo():
def __init__(self):
self.hands = {}
def insty(self):
self.hands['hand1'] = Hand()
self.hands['hand2'] = Hand()