Python class variable access speed - python

Say there is a class:
class x(obj):
y = 1
What is faster (or preferred):
def __init__(self):
print self.y
or:
def __init__(self):
print x.y
I assume x.y better communicates the intend but I'm interested in the speed implications.

The performance gain you could possibly achieve with these micro optimizations doesn't matter. The impact of the printing dwarfs the cost of attribute access by far. For reference, here's a test script:
import sys,timeit
class ClassAccess(object):
y = 1
def __init__(self):
print(ClassAccess.y)
class SelfAccess(object):
y = 1
def __init__(self):
print(self.y)
ca = timeit.timeit(ClassAccess, number=100000)
sa = timeit.timeit(SelfAccess, number=100000)
sys.stderr.write(str(ca) + "\n")
sys.stderr.write(str(sa) + "\n")
On my machine (with the yakuake terminal), this outputs
0.640013933182
0.628859043121
This is within experimental error of both variants being identical. Crude experimentation shows that:
Approximately 90% of the runtime is caused by actually displaying the printed result.
Of the rest, approximately 50% is the time that the print statement alone takes up.
Approximately 80% of the rest of that is caused by the allocation of the objects.
Therefore, it's safe to say to derive the conclusion that there is no difference in performance.

Note that depending on the class implementation the returned values may differ.
This returns the y attribute of the instance :
def __init__(self):
print self.y
While this returns the y attribute of the class :
def __init__(self):
print x.y
If the constructor override the y attribute a la :
def __init__(self, y=None):
self.y = y
def print(self):
print self.y
the returned values will differ.
Python looks up the instance internal dictionary checking for y before to check for the class internat dictionary.
So I think that print x.y should be slightly faster because it avoids looking up the instance dictionary.

Related

self in Python classes

I know first argument in Python methods will be an instance of this class. So we need use "self" as first argument in methods. But should we also specify attribures (variables) in method starting with "self."?
My method work even if i don't specify self in his attributes:
class Test:
def y(self, x):
c = x + 3
print(c)
t = Test()
t.y(2)
5
and
class Test:
def y(self, x):
self.c = x + 3
print(self.c)
t = Test()
t.y(2)
5
For what i would need specify an attribute in methods like "self.a" instead of just "a"?
In which cases first example will not work but second will? Want to see situation which shows really differences between two of them, because now they behave the same from my point of view.
The reason you do self.attribute_name in a class method is to perform computation on that instances attribute as opposed to using a random variable.For Example
class Car:
def __init__(self,size):
self.size = size
def can_accomodate(self,number_of_people):
return self.size> number_of_people
def change_size(self,new_size):
self.size=new_size
#works but bad practice
def can_accomodate_v2(self,size,number_of_people):
return size> number_of_people
c = Car(5)
print(c.can_accomodate(2))
print(c.can_accomodate_v2(4,2))
In the above example you can see that the can_accomodate use's self.size while can_accomodate_v2 passes the size variable which is bad practice.Both will work but the v2 is a bad practice and should not be used.You can pass argument into a class method not related to the instance/class for example "number_of_people" in can_accomodate funtion.
Hope this helps.

Best practice for defining a class that computes attributes in order when initialized

I would like to define a class that does something like:
Class computer():
def __init__(self, x):
# compute first the 'helper' properties
self.prop1 = self.compute_prop1(x)
self.prop2 = self.compute_prop2(x)
# then compute the property that depends on 'helpers'
self.prop3 = self.compute_prop3(x)
def compute_prop1(self, x):
return x
def compute_prop2(self, x):
return x*x
def compute_prop3(self, x):
return self.prop1 + self.prop2
Then, when I initialize an instance, I get all properties computed in order (first helpers, then everything depending on helpers later):
>>> computer = Computer(3)
>>> computer.__dict__
{'prop1': 3, 'prop2': 9, 'prop3': 12}
However, I think there is a better practice of writing this code, for example using decorators. Could you please give me some hints? Thank you!
Here's your class using properties instead (with an added method for returning each property):
Class PropertyComputer:
def __init__(self, x):
self._x = x
#property
def prop1(self):
return self._x
#property
def prop2(self):
return self._x * self._x
#property
def prop3(self):
return self.prop1 + self.prop2
def get_props(self):
return self.prop1, self.prop2, self.prop3
Design-wise, I believe this is better because:
storing x as an instance variable makes more sense: the point of using objects is to avoid having to pass variables around, especially those that the object itself can keep track of;
the attribute assignment and its corresponding calculation are bundled together in each property-decorated method: we'll never have to think whether the problem is in the init method (where you define the attribute) or in the compute method (where the logic for the attribute's calculation is laid out).
Note that the concept of "first calculate helpers, then the properties depending on them" does not really apply to this code: we only need to evaluate prop3 if/when we actually need it. If we never access it, we never need to compute it.
A "bad" side-effect of using properties, compared to your example, is that these properties are not "stored" anywhere (hence why I added the last method):
c = PropertyComputer(x=2)
c.__dict__ # outputs {'_x': 2}
Also note that, using decorators, the attributes are calculated on-the-fly whenever you access them, instead of just once in the init method. In this manner, property-decorated methods work like methods, but are accessed like attributes (it's the whole point of using them):
c = PropertyComputer(x=2)
c.prop1 # outputs 2
c._x = 10
c.prop1 # outputs 10
As a side note, you can use functools.cached_property to cache the evaluation of one of these properties, in case it's computationally expensive.
I think the following would be the easiest way to avoid redundancy
class computer():
def __init__(self, x):
self.prop_dict = self.compute_prop_dict(x)
def compute_prop_dict(self, x):
prop1 = x
prop2 = x*x
return {'prop1': prop1, 'prop2': prop2, 'prop3': prop1 + prop2}
So anything that would come after instantiation could have access to these helpers via the prop_dict
But as said by Brian as a comment this order is just a language specification for Python 3.7

Return different objects from a method, depending on whether method parameter is present

I am creating a class with a number of methods, as one of the steps, I want to change one of the args to call the new version in a different method from the class.
I am sure it’s something simple but I just can’t figure out where it is going wrong.
For brevity, I have tried to make a simple example from what I am actually coding.
class Double:
def __init__(self, x):
self.x = x
def double(self):
self.x = self.x * 2
# change the x item to x*2
return self.x
def return1(self, xg=x):
# if xg isn’t defined by user, this method should return
# the new version of x created above
return xg
I would also appreciate any other feedback on my class coding.
It is not clear what you are trying to accomplish and there is probably a better design, but to answer your question, you can use the following idiom:
def return1(self, xg=None):
return xg if xg is not None else self.x

Python setter not executed when setting nested property

I have the following Python code to represent the velocity of an object.
class Vector(object):
def __init__(self, x, y):
self.x, self.y = x, y
class Physics(object):
def __init__(self, velocity):
self.velocity = velocity
#property
def velocity(self):
return self._velocity
#velocity.setter
def velocity(self, velocity):
self._velocity = velocity
self._hi_res_velocity = Vector(velocity.x * 1000, velocity.y * 1000)
My intent is for velocity.x to set both _velocity.x and _hi_res_velocity.x, but the setter isn't run in this case. I get the following:
>>> myObject = Physics(Vector(10, 20))
>>> myObject.velocity.x = 30
>>> myObject._velocity.x, myObject._hi_res_velocity.x
(30, 10000)
I think the getter for velocity is run and then x is set on that returned value, but is it possible to implement the behavior I want using properties? I feel like I'll have to rewrite my logic to make this work.
When you do this:
myObject.velocity.x = 30
|_______________|
|
|___ this part already resolved the property
The myObject.velocity is already returning a Velocity instance, and this happens first. Then the .x which follows is just a normal attribute access, since the Vector class doesn't define a descriptor for handling x.
I'll suggest a different design, make either the "velocity" or the "hi_res_velocity" a getter-only, i.e. one of them is computed from the other whenever needed. This will resolve your issue, and also has the advantage that you don't have to store the same state twice.

Add to custom class in Python

I would like to be able to add to a custom class in the style of:
x=myclass("Something", 7)
x + 3
7, of course, corresponds with an inner property that I'd like to increment by adding to it.
The class holds a number that refers to a location in a list. This might seem like something that can be done by a normal integer, but I need it to act as a separate type. This is all done to emulate an old game language. The class is its 'variable' class, and the value of the variable is stored in the aforementioned list. Apparently, on older version of the game, arrays were faked by doing math on the variable object instance to grab a different variable. So I'm trying to emulate that.
If you want to support addition for class instances, you need to define an __add__() method on your class:
class MyClass(object):
def __init__(self, x):
self.x = x
def __add__(self, other):
return self.x + other
Example:
>>> a = MyClass(7)
>>> a + 3
10
To also support 3 + a, define the __radd__() method.
If you want to be able to update the x attribute of MyClass instances using
a += 3
you can define __iadd__().
If you want class instances to behave like integers with some additional methods and attributes, you should simply derive from int.
What you're looking to do is operator overloading. You can do this in python new style classes by overloading the __add__ method like so:
>>> class Test(object):
... def __init__(self): self.prop = 3
... def __add__(self, x):
... return self.prop + x
...
>>> Test() + 4
7
>>>

Categories