This question already has answers here:
How to change a module variable from another module?
(3 answers)
Closed last year.
I have this module which stores a class, an instance of that class, a counter, and a dictionary:
#test_module.py:
class TestClass:
def __init__(self, name='name', attr='attr'):
self.name = name
self.attr = attr
def func(self, test_list):
test_dict[count] = test_list[-1].name + '_' + test_list[-1].attr
test_inst = TestClass()
count = 0
test_dict = {}
What I want is for the dictionary to store each consecutive value of the counter (1,2,3...) as a key and the name and attribute of the last class instance in a test_list. (All the code here is simplified for the sake of reproducing the problem, the actual number of classes and instances is greater).
In a notebook, I have the following code:
from test_module import *
test_list = []
test_list.append(test_inst)
count += 1
test_list_item = test_list[-1]
test_dict[count] = test_list_item.name + '_' + test_list_item.attr
test_list.append(test_inst)
count += 1
test_list_item = test_list[-1]
test_list_item.func(test_list)
What now is in the dictionary is:
{1: 'name_attr', 0: 'name_attr'}
Why am I getting zero as the second key?
I've tried specifying the count and the test_dict as global variables in the TestClass definition, but to no avail.
All works OK if I copy the contents of the test_module into the notebook, but this is not what I'm after. My goal is to have as much code as possible in the test_module. What am I doing wrong? How can I make it work properly?
I just copied your code and the output is
{1: 'name_attr', 2: 'name_attr'}
While learning about how classes work in Python I came across a class definition example which behaved kind of strangely in my eyes.
The purpose of the example was to demonstrate how the behaviour of a static variable can be achieved in Python. The example was written as follows:
class MemberCounter:
members = 0
def init(self):
MemberCounter.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
after setting up the class and creating the objects, I printed the values of the 'members' attribute. These were the results:
MemberCounter.members = 2
m1.members = 2
m2.members = 2
And that's when I got confused. While I was expecting for 'MemberCounter.members = 2' the two other results made no sense to me - why would both of 'm1' and 'm2' objects' 'members' value be equal to 2? I thought that both of the values should have been 0 - if the only attribute that was chaged is the 'members' attribute which was attached to the MemberCounter class why would it cause any change to the own unique 'members' value of each of the class' objects. It looks like the fact that the 'members' attribute is addresed like 'MemberCounter.members += 1' in the init() function of each object, completely overrides the unique values which m1.members and m2.members refer to and redirects their pointers to the MemberCounter.members value making all the three pointers point at the same value
==> m1.members = m2.members = MemberCounter.members.
Moreover, I have tried defining the class in an opossite way (Increasing self.members instead of MemberCounter.members):
class MemberCounter:
members = 0
def init(self):
self.members += 1
m1 = MemberCounter()
m1.init()
m2 = MemberCounter()
m2.init()
This definition yielded logical results (which got me curious about the above mentioned strange behaviour even more):
MemberCounter.members = 0
m1.members = 1
m2.members = 1
In short, I was curious about why the first class definition behaves in such a strange way? Why the mere 'MemberCounter.members += 1' statement completely erased 'm1.members' and 'm2.members' own unique value and made it equal to the MemberCounter.members value.
I hope I was able to clearly present my problem and I will be extremly happy to get an insight about this strange behaviour :)
That you can read a static attribute with instance.attribute notation as alternative to the more natural class.attribute notation, is an intended feature in Python.
From the documentation:
Both static data and static methods (in the sense of C++ or Java) are supported in Python.
For static data, simply define a class attribute. To assign a new
value to the attribute, you have to explicitly use the class name in
the assignment:
class C:
count = 0 # number of times C.__init__ called
def __init__(self):
C.count = C.count + 1
def getcount(self):
return C.count # or return self.count
c.count also refers to C.count for any c such that
isinstance(c, C) holds, unless overridden by c itself or by some
class on the base-class search path from c.__class__ back to C.
Caution: within a method of C, an assignment like self.count = 42
creates a new and unrelated instance named “count” in self’s own dict.
Rebinding of a class-static data name must always specify the class
whether inside a method or not:
C.count = 314
The paragraph just below the first code block explains your doubts. The "Caution" paragraph explains what you found logical.
I have class for calculating temperatures of an object at different positions, based on ambient temperature. I have two ways of implementation. In BodyA, the temperature of each position is an attribute of the class; while in BodyB, there is an attribute pos_t, which is a dict, and the temperature of each position is just a key-value pair in the dict.
class BodyA:
def __init__(self, ambient_temperature)
self.amb_t = ambient_temperature
self.pos1_t = self.amb_t + 1
self.pos2_t = self.amb_t * 2
self.pos3_t = self.pos1_t + self.pos2_t - 5
class BodyB:
def __init__(self, ambient_temperature)
self.amb_t = ambient_temperature
self.pos_t = dict()
self.pos_t['pos1'] = self.amb_t + 1
self.pos_t['pos2'] = self.amb_t * 2
self.pos_t['pos3'] = self.pos_t['pos1'] + self.pos_t['pos2'] - 5
In practical case, there are up-to 10 positions, and I want to build child-class from it. And some child-classes do not have certain positions. For example, pos2 can be missing in some child.
Could you please let me know, which design is better in terms of OOP and efficiency. Thanks.
A data structure to store some custom identifiers that may or may exist calls clearly for a dict. As class attributes are also stored in an internal dict, the first approach can be used too, but to have pratical manipulation without explicit hand writing the members will require different code. I suspect performance will not matter. If you find it matters, maybe a redesign of the data structure that does not use classes at all will do, as object creation processing time may be relevant then.
Yes, this question has been asked before. No, none of the answers I read could fix the problem I have.
I'm trying to create a little Bounce game. I've created the bricks like this:
def __init__(self,canvas):
self.canvas = canvas
self.brick1 = canvas.create_rectangle(0,0,50,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick2 = canvas.create_rectangle(50,0,100,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick3 = canvas.create_rectangle(100,0,150,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick4 = canvas.create_rectangle(150,0,200,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick5 = canvas.create_rectangle(200,0,250,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick6 = canvas.create_rectangle(250,0,300,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick7 = canvas.create_rectangle(300,0,350,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick8 = canvas.create_rectangle(350,0,400,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick9 = canvas.create_rectangle(400,0,450,20,fill=random_fill_colour(),outline=random_fill_colour())
self.brick10 = canvas.create_rectangle(450,0,500,20,fill=random_fill_colour(),outline=random_fill_colour())
self.bricksId = [self.brick1,self.brick2,self.brick3,self.brick4,self.brick5,self.brick6,self.brick7,self.brick8,self.brick9,self.brick10]
And I'm trying to reference the ID of bricksId[0] over here:
self.hit_brick(pos,self.bricks.bricksId[0])
Earlier, in the __init__, I define bricks as bricks, which is defined as Brick(canvas). However, the error states:
TypeError: 'Brick' object does not support indexing
In the answers to the other questions of this subject, I cannot find any that help me access bricks.bricksId[0].
In order for the Brick object to be indexable, you must implement the methods:
__getitem__
__setitem__
__delitem__
You don't need all of them, only the ones you use.
However, this seems like a case of self.bricks being a brick instead of a list of bricks. A list of bricks is indexable; however, a brick itself is not unless you implement the methods above.
Check this for reference.
In order to be able to call self.bricks.bricksId[number] when I needed:
def __getitem__(self,index):
return self.bricks.bricksId[index]
def __setitem__(self,index,value):
self.bricks.bricksId[index] = value
Doing a class and finished with the rest less this one. Any guidance is appreciated. I have derived part of the question where I am stuck with to keep it short. I have also attached my working. Question as follows:
Create a class with 1 variable in it holding its own properties.
Provide the following 3 methods:
getvariable1() - use return key tp return value of property 1
setvariable1() - This should allow new value to be specified for property 1 - additional parameter needed to accept input.
printerfun() - to print values of the variables for the object.
Create your own object of the class and call get & set methods for the object created. Use printerfun() method to check if the codes works.
My working:
class animal:
horns = 2
def printerfun(self):
print getHorns()
def getHorns(self): #don't get where I should call this
return self.horns
def setHorns(horns):
self.horns = horns
animal_1 = animal()
F1 = raw_input('Please enter number of horns: ')
setHorns(F1)
Not sure what the question is, but anyway...
You should write a __init__ member function to create the initial member variables:
class animal:
def __init__(self):
self.horns = 2
Your code creates a class variable, not a normal member variable.
Then change the horns with:
animal_1.setHorns(F1)
Your code doesn't say which animal you want to change the variable to.