Related
I am confused about use of property class with regard to references to the fset/fget/fdel functions and in which namespaces they live. The behavior is different depending on whether I use property as a decorator or a helper function. Why do duplicate vars in class and instance namespaces impact one example but not the other?
When using property as a decorator shown here I must hide the var name in __dict__ with a leading underscore to prevent preempting the property functions. If not I'll see a recursion loop.
class setget():
"""Play with setters and getters"""
#property
def x(self):
print('getting x')
return self._x
#x.setter
def x(self, x):
print('setting x')
self._x = x
#x.deleter
def x(self):
print('deleting x')
del self._x
and I can see _x as an instance property and x as a class property:
>>> sg = setget()
>>> sg.x = 1
setting x
>>> sg.__dict__
{'_x': 1}
pprint(setget.__dict__)
mappingproxy({'__dict__': <attribute '__dict__' of 'setget' objects>,
'__doc__': 'Play with setters and getters',
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'setget' objects>,
'x': <property object at 0x000001BF3A0C37C8>})
>>>
Here's an example of recursion if the instance var name underscore is omitted. (code not shown here) This makes sense to me because instance property x does not exist and so we look further to class properties.
>>> sg = setget()
>>> sg.x = 1
setting x
setting x
setting x
setting x
...
However if I use property as a helper function as described in one of the answers here:
python class attributes vs instance attributes
the name hiding underscore is not needed and there is no conflict.
Copy of the example code:
class PropertyHelperDemo:
'''Demonstrates a property definition helper function'''
def prop_helper(k: str, doc: str):
print(f'Creating property instance {k}')
def _get(self):
print(f'getting {k}')
return self.__dict__.__getitem__(k) # might use '_'+k, etc.
def _set(self, v):
print(f'setting {k}')
self.__dict__.__setitem__(k, v)
def _del(self):
print(f'deleting {k}')
self.__dict__.__delitem__(k)
return property(_get, _set, _del, doc)
X: float = prop_helper('X', doc="X is the best!")
Y: float = prop_helper('Y', doc="Y do you ask?")
Z: float = prop_helper('Z', doc="Z plane!")
# etc...
def __init__(self, X: float, Y: float, Z: float):
#super(PropertyHelperDemo, self).__init__() # not sure why this was here
(self.X, self.Y, self.Z) = (X, Y, Z)
# for read-only properties, the built-in technique remains sleek enough already
#property
def Total(self) -> float:
return self.X + self.Y + self.Z
And here I verify that the property fset function is being executed on subsequent calls.
>>> p = PropertyHelperDemo(1, 2, 3)
setting X
setting Y
setting Z
>>> p.X = 11
setting X
>>> p.X = 111
setting X
>>> p.__dict__
{'X': 111, 'Y': 2, 'Z': 3}
>>> pprint(PropertyHelperDemo.__dict__)
mappingproxy({'Total': <property object at 0x000002333A093F98>,
'X': <property object at 0x000002333A088EF8>,
'Y': <property object at 0x000002333A093408>,
'Z': <property object at 0x000002333A093D18>,
'__annotations__': {'X': <class 'float'>,
'Y': <class 'float'>,
'Z': <class 'float'>},
'__dict__': <attribute '__dict__' of 'PropertyHelperDemo' objects>,
'__doc__': 'Demonstrates a property definition helper function',
'__init__': <function PropertyHelperDemo.__init__ at 0x000002333A0B3AF8>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'PropertyHelperDemo' objects>,
'prop_helper': <function PropertyHelperDemo.prop_helper at 0x000002333A052F78>})
>>>
I can see the class and instance properties with overlapping names X, Y, Z, in the two namespaces. It is my understanding that the namespace search order begins with local variables so I don't understand why the property fset function is executed here.
Any guidance is greatly appreciated.
I think you're a little astray in construing _x as an "instance property" and x as a "class property" - in fact, both are bound to the instance only, and neither is bound to the other except by the arbitrarily defined behaviour of the method decorated by #property.
They both occupy the same namespace, which is why, though they may represent the same quantity, they cannot share a name for fear of shadowing/confusing the namespace.
The issue of namespaces is not directly connected to the use of the #property decorator. You don't HAVE to "hide" the attribute name - you just need to ensure that the attribute name differs from the name of the method, because once you apply the #property decorator, the method decorated by #property can be accessed just like any other attribute without a typical method call signature including the ().
Here's an example, adjacent to the one you provided, that may help clarify. I define a class, PositionVector below, that holds the x, y and z coordinates of a point in space.
When initialising an instance of the class, I also create an attribute length that computes the length of the vector based on the x, y and z values. Trying this:
import numpy as np
class PositionVector:
def __init__(self, x: float, y: float, z: float) -> None:
self.x = x
self.y = y
self.z = z
self.length = np.sqrt(x**2 + y**2 + z**2)
p1 = PositionVector(x = 10, y = 0, z = 0)
print (p1.length)
# Result -> 10.0
Only now I want to change the y attribute of the instance. I do this:
p1.y = 10.0
print (f"p1's 'y' value is {p1.y}")
# Result -> p1's 'y' value is 10.0
Except now, if I again access the length of the vector, I get the wrong answer:
print (f"p1's length is {p1.length}")
# Result -> p1's length is 10.0
This arises because length, which at any given instant depends on the current values of x, y, and z, is never updated and kept consistent. We could fix this issue by redefining our class so length is a method that is continuously recalculated every time the user wants to access it, like so:
class PositionVector:
def __init__(self, x: float, y: float, z: float) -> None:
self.x = x
self.y = y
self.z = z
def length(self):
return np.sqrt(self.x**2 + self.y**2 + self.z**2)
Now, I have a way to get the correct length of an instance of this class at all times by calling the instance's length() method:
p1 = PositionVector(x = 10, y = 0, z = 0)
print (f"p1's length is {p1.length()}")
# Result -> p1's length is 10.0
p1.y = 10.0
print (f"p1's 'y' value is {p1.y}")
# Result -> p1's 'y' value is 10.0
print (f"p1's length is {p1.length()}")
# Result -> p1's length is 14.142135623730951
This is fine, except for two issues:
If this class had been in use already, going back and changing length from an attribute to a method would break backward compatibility, forcing any other code that uses this class to need modifications before it could work as before.
Though I DO want length to recalculate every time I invoke it, I want to be able to pick it up and "handle" it like it's a "property" of the instance, not a "behaviour" of the instance. So using p1.length() to get the instance's length instead of simply p1.length feels unidiomatic.
I can restore backward compatibility, AND permit length to be accessed like any other attribute by applying the #property decorator to the method. Simply adding #property to the length() method definition allows its call signature to go back to its original form:
#property
def length(self):
return np.sqrt(self.x**2 + self.y**2 + self.z**2)
p1 = PositionVector(x=10, y=0, z=0)
print(f"p1's length is {p1.length}")
# Result -> p1's length is 10.0
p1.y = 10.0
print(f"p1's 'y' value is {p1.y}")
# Result -> p1's 'y' value is 10.0
print(f"p1's length is {p1.length}")
# Result -> p1's length is 14.142135623730951
At this point, there are no shadowed or "underscored" attribute names, I don't need them - I can access x, y and z normally, and access length as though it were any other attribute, and yet be confident that anytime I call it, I get the most current value, correctly reflective of the current values of x, y, and z. Calling dict on p1 in this state yields:
print(p1.__dict__)
# Result -> {'x': 10, 'y': 10.0, 'z': 0}
There could be use cases where you want to not only calculate length, but also save its value as a static attribute of an instance. This is where you might want to create an attribute and have it hold the value of length every time its calculated. You'd accomplish this like so:
class PositionVector:
def __init__(self, x: float, y: float, z: float) -> None:
self.x = x
self.y = y
self.z = z
self.placeholder_attribute_name = None
#property
def length(self):
self.placeholder_attribute_name = np.sqrt(self.x**2 + self.y**2 + self.z**2)
return self.placeholder_attribute_name
Doing this has no effect whatsoever on the prior functioning of the class. It simply creates a way to statically hold the value of length, independent of the act of creating it.
You don't HAVE to name that attribute anything in particular. You can name it anything you want, except for any other name already in use. In the case above, you can't name it x, y, z, or length, because all of those have other meanings.
For readability, however, it does make sense, and it's common practice, to do the following two things:
Make it obvious that this attribute is not meant to be used directly. In the case above - you don't want someone to get the length of the vector by calling p1.placeholder_attribute_name because this is not guaranteed to yield the correct current length - they should use p1.length instead. You indicate that this attribute is not for public consumption with a commonly adopted Python convention - the leading underscore:
class PositionVector:
def __init__(self, x: float, y: float, z: float) -> None:
self.x = x
self.y = y
self.z = z
self._placeholder_attribute_name = None
#property
def length(self):
self._placeholder_attribute_name = np.sqrt(self.x**2 + self.y**2 + self.z**2)
return self._placeholder_attribute_name
Use the name of the attribute to convey to anyone reading your code what the attribute actually means. If the attribute is meant to shadow the "length" property - putting length in there somewhere instead of the less helpful placeholder_attribute_name would enhance readability. You could indicate that this shadows length by naming it _length.
In summary:
Employing the #property decorator does not compel you to use "public" and "private" attribute names - you would only do so if, besides computing your attribute's value with the #property decorated method, you also wanted to save the value of that method's return in a persistent attribute bound to every instance of the class.
Even when you DO choose to use propertyname in public and _propertyname in private this is not an absolute rule, it is simply a convention adopted in aid of readability.
Thanks to #Vin for a nice detailed description of property but it doesn't really answer my question - which could have been worded much more clearly. It shows my confusion.
The fundamental reason for the recursion in setget but not PropertyHelperDemo is that the property methods in setget invoke themselves while the methods in PropertyHelperDemo access the instance __dict__ directly as such:
def _get(self):
print(f'getting {k}')
return self.__dict__.__getitem__(k)
This seems rather obvious now. It is apparent that conflicting property and __dict__ attribute names are not prevented and that the resolution order is to look for properties before __dict__ entries.
In other experiments I've found that it's possible to replace an instance method by making an entry of the same name in __dict__. So the overall resolution sequence remains less than clear (to me.)
Another source of confusion for me is that dir returns a list of names of methods plus __dict__ entries and other attributes, and apparently eliminates duplicates. From the doc:
If the object does not provide __dir__(), the function tries its best
to gather information from the object’s __dict__ attribute, if
defined, and from its type object. The resulting list is not
necessarily complete, and may be inaccurate when the object has a
custom __getattr__().
... If the object is a type or class object, the list contains the names
of its attributes, and recursively of the attributes of its bases.
... The resulting list is sorted alphabetically.
Interestingly, properties appear in the class __dict__ but not in the instance __dict__.
I found this in the Descriptor HowTo Guide offered by #chepner. THANKS!
The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance, a.x has a lookup chain starting with a.__dict__['x'], then type(a).__dict__['x'], and continuing through the method resolution order of type(a). If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. Where this occurs in the precedence chain depends on which descriptor methods were defined.
... Instance lookup scans through a chain of namespaces giving data descriptors the highest priority, followed by instance variables, then non-data descriptors, then class variables, and lastly __getattr__() if it is provided.
A Python property is a type of descriptor so resolution through __dict__ is preempted.
Another way to explore is using inspect which does not eliminate duplicates.
>>> p = PropertyHelperDemo(1, 2, 3)
setting X
setting Y
setting Z
>>>
>>> import inspect
>>> pprint(inspect.getmembers(p))
getting X
getting Y
getting Z
getting X
getting Y
getting Z
[('Total', 6),
('X', 1),
('Y', 2),
('Z', 3),
('__annotations__',
{'X': <class 'float'>, 'Y': <class 'float'>, 'Z': <class 'float'>}),
('__class__', <class '__main__.PropertyHelperDemo'>),
('__delattr__',
<method-wrapper '__delattr__' of PropertyHelperDemo object at 0x00000181D14C6608>),
('__dict__', {'X': 1, 'Y': 2, 'Z': 3}),
('__dir__',
<built-in method __dir__ of PropertyHelperDemo object at 0x00000181D14C6608>),
...
...
...
>>> pprint(inspect.getmembers(p, predicate=inspect.ismethod))
getting X
getting Y
getting Z
getting X
getting Y
getting Z
[('__init__',
<bound method PropertyHelperDemo.__init__ of <__main__.PropertyHelperDemo object at 0x00000181D14C6608>>),
('prop_helper',
<bound method PropertyHelperDemo.prop_helper of <__main__.PropertyHelperDemo object at 0x00000181D14C6608>>)]
>>>
In the first listing we can see the property methods as well as the __dict__ attributes. It's interesting (to me) that the property methods are executed by inspect. We see methods X, Y, Z executed twice because Total also calls them. Properties X, Y, Z and Total are not listed when we filter for methods.
Of course it's a great idea to re-use names like this only if you want to drive yourself and everyone else crazy.
Enough omphaloskepsis, it's time to move on.
I try to process some data in Python and I defined a class for a sub-type of data. You can find a very simplified version of the class definition below.
class MyDataClass(object):
def __init__(self, input1, input2, input3):
"""
input1 and input2 are a 1D-array
input3 is a 2D-array
"""
self._x_value = None # int
self._y_value = None # int
self.data_array_1 = None # 2D array
self.data_array_2 = None # 1D array
self.set_data(input1, input2, input3)
def set_data(self, input1, input2, input3):
self._x_value, self._y_value = self.get_x_and_y_value(input1, input2)
self.data_array_1 = self.get_data_array_1(input1)
self.data_array_2 = self.get_data_array_2(input3)
#staticmethod
def get_x_and_y_value(input1, input2):
# do some stuff
return x_value, y_value
def get_data_array_1(self, input1):
# do some stuff
return input1[self._x_value:self._y_value + 1]
def get_data_array_2(self, input3):
q = self.data_array_1 - input3[self._x_value:self._y_value + 1, :]
return np.linalg.norm(q, axis=1)
I'm trying to follow the 'Zen of Python' and thereby to write beautiful code. I'm quite sceptic, whether the class definition above is a good pratice or not. While I was thinking about alternatives I came up with the following questions, to which I would like to kindly get your opinions and suggestions.
Does it make sense to define ''get'' and ''set'' methods?
IMHO, as the resulting data will be used several times (in several plots and computation routines), it is more convenient to create and store them once. Hence, I calculate the data arrays once in the constructor.
I do not deal with huge amount of data and therefore processing takes not more than a second, however I cannot estimate its potential implications on RAM if someone would use the same procedure for huge data.
Should I put the function get_x_and_y_value() out of the class scope and convert static method to a function?
As the method is only called inside the class definition, it is better to use it as a static method. If I should define it as a function, should I put all the lines relevant to this class inside a script and create a module of it?
The argument naming of the function get_x_and_y_value() are the same as __init__ method. Should I change it?
It would ease refactoring but could confuse others who read it.
In Python, you do not need getter and setter functions. Use properties instead. This is why you can access attributes directly in Python, unlike other languages like Java where you absolutely need to use getters and setters and to protect your attributes.
Consider the following example of a Circle class. Because we can use the #property decorator, we don't need getter and setter functions like other languages do. This is the Pythonic answer.
This should address all of your questions.
class Circle(object):
def __init__(self, radius):
self.radius = radius
self.x = 0
self.y = 0
#property
def diameter(self):
return self.radius * 2
#diameter.setter
def diameter(self, value):
self.radius = value / 2
#property
def xy(self):
return (self.x, self.y)
#xy.setter
def xy(self, xy_pair):
self.x, self.y = xy_pair
>>> c = Circle(radius=10)
>>> c.radius
10
>>> c.diameter
20
>>> c.diameter = 10
>>> c.radius
5.0
>>> c.xy
(0, 0)
>>> c.xy = (10, 20)
>>> c.x
10
>>> c.y
20
In this case, I want that the program print "X = changed"
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
self.var = 'changed'
X = 'unchanged'
V = Clase(X)
V.set_var()
print "X = ",X
All values are objects and are passed by reference in Python, and assignment changes the reference.
def myfunc(y):
y = 13
x = 42 # x now points at the integer object, 42
myfunc(y) # inside myfunc, y initially points to 42,
# but myfunc changes its y to point to a
# different object, 13
print(x) # prints 42, since changing y inside myfunc
# does not change any other variable
It's important to note here that there are no "simple types" as there are in other languages. In Python, integers are objects. Floats are objects. Bools are objects. And assignment is always changing a pointer to refer to a different object, whatever the type of that object.
Thus, it's not possible to "assign through" a reference and change someone else's variable. You can, however, simulate this by passing a mutable container (e.g. a list or a dictionary) and changing the contents of the container, as others have shown.
This kind of mutation of arguments through pointers is common in C/C++ and is generally used to work around the fact that a function can only have a single return value. Python will happily create tuples for you in the return statement and unpack them to multiple variables on the other side, making it easy to return multiple values, so this isn't an issue. Just return all the values you want to return. Here is a trivial example:
def myfunc(x, y, z):
return x * 2, y + 5, z - 3
On the other side:
a, b, c = myFunc(4, 5, 6)
In practice, then, there is rarely any reason to need to do what you're trying to do in Python.
In python list and dict types are global and are passed around by reference. So if you change the type of your variable X to one of those you will get the desired results.
[EDIT: Added use case that op needed]
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
self.var.test = 'changed'
class ComplicatedClass():
def __init__(self, test):
self.test = test
X = ComplicatedClass('unchanged')
print('Before:', X.test)
V = Clase(X)
V.set_var()
print("After:",X.test)
>>> Before: unchanged
>>> After: changed
strings are immutable so you could not change X in this way
... an alternative might be reassigning X in the global space... this obviously will fail in many many senarios (ie it is not a global)
class Clase:
def __init__(self,variable):
self.var = variable
def set_var(self):
globals()[self.var] = 'changed'
X = 'unchanged'
V = Clase('X')
V.set_var()
print "X = ",X
the other alternative is to use a mutable data type as suggested by Ashwin
or the best option is that this is probably not a good idea and you should likely not do it...
I was just wondering when to store things as part of a class instance versus when to use a method to return things. For example, which of the following would be better:
class MClass():
def __init__(self):
self.x = self.get_x()
self.get_y()
self.z = None
self.get_z()
def get_x(self):
return 2
def get_y(self):
self.y = 5 * self.x
def get_z(self):
return self.get_x() * self.x
What are the conventions regarding this sort of thing and when should I assign things to self and when should I return values? Is this essentially a public/private sort of distinction?
You shouldn't return anything from __init__.
Python is not Java. You don't need to include get for everything.
If x is always 2 and y is always 10 and z is always 12, that is a lot of code.
Making some assumptions, I would write that class:
class MClass(object):
def __init__(self, x):
self.x = x
def y(self):
return self.x * 5
def z(self):
return self.x + self.y()
>>> c = MClass(2)
>>> c.x
2
>>> c.y() # note parentheses
10
>>> c.z()
12
This allows x to change later (e.g. c.x = 4) and still give the correct values for y and z.
You can use the #property decorator:
class MClass():
def __init__(self):
self.x = 2
#property
def y(self):
return 5 * self.x
#here a plus method for the setter
#y.setter
def y(self,value):
self.x = y/5
#property
def z(self):
return self.x * self.x
It's a good way of organizing yours acessors
There's no "conventions" regarding this, AFAIK, although there're common practices, different from one language to the next.
In python, the general belief is that "everything is public", and there's no reason at all to have a getter method just to return the value of a instance variable. You may, however, need such a method if you need to perform operations on the instance when such variable is accessed.
Your get_y method, for example, only makes sense if you need to recalculate the expression (5 * self.x) every time you access the value. Otherwise, you should simply define the y variable in the instance in __init__ - it's faster (because you don't recalculate the value every time) and it makes your intentions clear (because anyone looking at your code will immediately know that the value does not change)
Finally, some people prefer using properties instead of writing bare get/set methods. There's more info in this question
I read your question as a general Object Oriented development question, rather than a python specific one. As such, the general rule of member data would be to save the data as a member of the class only if it's relevant as part of a particular instance.
As an example, if you have a Screen object which has two dimensions, height and width. Those two should be stored as members. The area associated with a particular instance would return the value associated with a particular instance's height and width.
If there are certain things that seem like they should be calculated on the fly, but might be called over and over again, you can cache them as members as well, but that's really something you should do after you determine that it is a valid trade off (extra member in exchange for faster run time).
get should always do what it says. get_y() and get_z() don't do that.
Better do:
class MClass(object):
def __init__(self):
self.x = 2
#property
def y(self):
return 5 * self.x
#property
def z(self):
return self.x * self.x
This makes y and z always depend on the value of x.
You can do
c = MClass()
print c.y, c.z # 10, 4
c.x = 20
print c.y, c.z # 100, 400
I'm new to python and am trying to create a program to test some methods of object creation. Currently, I'm writing a program that involves creating objects, giving them a unique numeric variable, and assigning them to a list for future referencing. Here's what I wrote to create the variable names:
def getRectangleName():
rectName = list("Rectangle")
SPAWNEDOBJECTLIST.append(len(SPAWNEDOBJECTLIST))
rectName.append(str(len(SPAWNEDOBJECTLIST)))
return rectName
and then that's passed onto something to turn that string into a variable name. I tried eval(), learned this was Bad for some reason and it didn't work anyway, and tried some workarounds to no avail.
I figure there's plenty of games that have an indefinite number of characters on the screen. Is there an established way of making iterations of objects like this?
The objects themselves have an X and Y so that they act as reference points for the display of rectangles on screen(the idea in the future is to have each one move around on their own, so simply making lists of X and Y to draw rectangles isn't useful).
Edit: The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Edit2: I don't think I'm asking the right question, actually, or using the right terminology. I need to be able to have an indefinite number of objects created on the fly after the program is already running, and be able to reference them individually.
The problem is that I don't know how to give each object its own variable to put it on a list for future referencing.
Whenever you think you need variables you didn't type into your program, you're doing something wrong. You don't need to assign something to a variable to put it on a list:
x = [1, 2, 3] # Note how I don't assign 1, 2, or 3 to variables.
x.append(4) # 4 doesn't get a variable either.
x.append(make_a_rectangle()) # We create a rectangle and stick it on the list.
do_stuff_with(x[4]) # We pass the rectangle to a function.
x = [] # New list.
for i in xrange(n):
x.append(make_a_rectangle()) # This happens n times.
# At this point, we have n rectangles, none of them associated with their own
# variable, none of them with a name.
If you think you need names for things (and quite often, you don't really need the names), you can use a dict:
x = {}
x['foo'] = make_a_rectangle()
do_stuff_with(x['foo'])
It's not a great idea to combine the function of managing the rectangles -- accessing, adding, or deleting them -- with the idea of being rectangles. You never know when you might need to maintain multiple lists, or change from unordered lists to organized ones.
Until you really need more, keep the management functions simple: use built-in lists or dictionaries. Use lists if you just care about ordering, or only need to know you have a bunch of stuff:
class Rectangle (object):
def __init__(self, top, bottom, left, right):
self.Top = top
self.Left = left
self.Right = right
self.Bottom = bottom
list_of_rects = [Rectangle(10,0,0,10), Rectangle(20, 10, 10 ,20)]
# how many rects?
len(list_of_rects)
# result: 2
# where is this particular rect?
fred = Rectangle(30,20,20, 30)
list_of_rects.insert(fred, 1)
list_of_rects.index(fred)
# result: 1
#remove an item from the list:
list_of_rects.remove(fred)
#search the list:
right_of_5 = [rect for rect in list_of_rects if rect.Left > 5]
If you need to get access to the individual rects for some reason -- 'what's the rectangle of the goal' or something -- you have two choices:
1) the code that needs the rect just keeps a reference to it:
class Goal(object):
def __init__(self, rect):
self.Rect = rect
goalrect = Rectangle (0,0,20,20)
mygoal = Goal(goalrect)
list_of_rects.append(goalrect)
# now goalrect always knows about it's own rect, but the list can keep track of it too...
2) Or, use a dictionary:
named_rects = {}
named_rects['goal'] = Rectangle(0,0,20,20)
You get all the same abilities with a dictionary that you do with a list -- add, delete, and find -- except dictionaries don't preserve order, so you can't manage things like priority:
# add to the dict:
named_rects['new_rect'] = Rectangle(90,90,95,95)
# remove
del named_rects['new_rect']
# find = is there a known key?
if 'new_rect' in named_rects: print new_rect
# search:
right_of_5 = [rect for rect in named_rects.items() if rect.Left > 5]
There are cases where you need fancier things than plain old lists and dicts -- but always try it with the free stuff first :)
If you dynamically want to create variables and add them to class instances, use this
class MainClass:
def __setattr__(self, name, value):
self.__dict__[name] = value
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].Temp = 10
print ClassInstances["Rectangle1"].Temp
If the class is going to have only X and Y,
class MainClass:
X, Y = 0, 0
def getRectangleNameGenerator(N = 10):
X = 0
while X <= N:
X += 1
yield "Rectangle" + str(X)
RectangleName = getRectangleNameGenerator()
ClassInstances = {next(RectangleName) : MainClass}
ClassInstances[next(RectangleName)] = MainClass
ClassInstances["Rectangle1"].X = 11
print ClassInstances["Rectangle1"].X
If you really want to refer to your rectangle instances by name, I would suggest to keep a dictionary at class level. Something like this:
#! /usr/bin/python3
from threading import Lock
import random
class Rectangle:
instances = {}
lock = Lock ()
#classmethod
def forName (cls, name):
return cls.instances [name] if name in cls.instances else None
#classmethod
def push (cls, inst):
with cls.lock:
name = None
while not name or name in cls.instances:
name = ''.join (random.choice ('abcdefghij') for i in range (16) )
cls.instances [name] = inst
return name
def __init__ (self):
self.name = Rectangle.push (self)
names = [Rectangle ().name for i in range (5) ]
for name in names:
print (name, Rectangle.forName (name) )