Is there any way to get this to work?
class A:
def method(self):
x = 5
y = 2
method.z = x * y
class B(A):
def method(self):
super().method()
z = super().method().z
xyz = 2**z
def main():
a = A().method()
b = B().method()
main()
Running it gives
NameError: name 'method' is not defined
The idea is that the super class does preliminary work that all subclasses would need to perform, and passes the result on to the subclass for use (in this case z).
Because the data is only needed in the scope of the subclass method calls, it doesn't make sense to store it in the scope of the class as an instance variable.
The above code is using notation found here, in search of C static function variables in python.
Related
I don't seam to be able to do this but is would make sense that you could.
So mybe I just made a mistake.
class Foobar:
def __init__(self):
self.myatr = 0
def add(self, someinput=self.myatr): # <-- someinput=self.myatr???
return someinput += 1
but you get the error
NameError: name 'self' is not defined
But it would be logicl if the this was the way it worket
f = Foobar()
f.add() # returns 1
f.add(1) # returns 2
Instance methods are functions bound to class attributes, defined when the class is defined, before any instance exists. Similarly, the default value is set once, at definition time, not on-demand when the method is called without an explicit argument.
As such, you need a sentinel (typically None) which signals that no argument was passed.
def add(self, someinput=None):
if someinput is None:
someinput = self.myatr
return someinput + 1
Default arguments are evaluated at function definition. Moreover, the names of the arguments defined earlier (like self in your function) aren't available during function definition. So when you refer to self.myattr, there's no self yet.
For example, consider this function:
>>> def test(thing=print('hello')):
... ...
...
hello
>>>
The expression print('hello') was evaluated right when the function was defined, and it won't be re-evaluated when you call test.
Also, return someinput += 1 is an error too because assignment is not an expression.
Furthermore, integers are always copied, so if you do this:
def test(x):
x += 1
return x
a = 6
test(a)
a will still be equal to six, since the call test(a) copied a.
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
is there any difference between these two method?
option1 :
class a(object):
def __init__(self):
self.x = 123
self.y = 345
option2 :
class a(object):
x = 123
y = 345
is there any difference between these two options?
Thanks in advance.
An example of the first method (instance level variables):
instance0 = a()
instance1 = b()
instance0.x = 5
print instance1.x # prints 123
print a.x # undefined variable - x is not defined
An example of the second method (class level variables):
instance0 = a()
instance1 = b()
instance0.x = 5
print instance1.x # prints 5
print a.x # prints 5
The second method, the variables are assigned at the class level meaning changing this value propagates to all instances of that class. You can also access the variables without an instance of the class.
Yes, in the first case each object of class a has its own copy of x and y, in the second case all objects of class a share them.
By the way, if your starting out with Python, use a capital for the first character of your class names, e.g. MyClass. People are used to that and it will help you understand your own programs once they get bigger.
I am new to python and i am not sure how this is working. Code is as below:
class test():
d=0
def __init__(self):
self.d=self.d+1;
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
Output is
1,1,1 # This should not be
Now using this :
class test():
d=[]
def __init__(self):
self.d.apend("1");
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
Result is (This should be)
['1']
['1', '1']
['1', '1', '1']
So i am not sure why integer value is not being treated as class variable while list is being treated.
In the first example,
self.d = self.d + 1
rebinds self.d, making it independent of test.d.
In the second example,
self.d.append("1")
modifies test.d.
To see that for yourself, print id(self.d) at the end of both constructors.
If you modified the second example to match the first:
self.d = self.d + ["1"]
you'd see that the behaviour would also change to match.
If you want to modify a class variable, do:
class test(object):
d=0
def __init__(self):
type(self).d=self.d+1;
D=test()
print D.d
D1=test()
print D1.d
D2=test()
print D2.d
You don't need the type on the right hand side of the assignment, because this way you never create an instance variable d. Note that new-style classes are necessary to this.
type is a function (actually a callable - it is also a class; but don't worry about that for now) which returns the class of its argument. So, type(self) returns the class of self. Classes are first class objects in Python.
Demo here: http://ideone.com/JdNpiV
Update: An alternative would be to use a classmethod.
To address a class variable use class_name.variable_name, giving :
class test(object):
d=0
def __init__(self):
test.d = test.d + 1;
NPE's answer tells you what is going wrong with your code. However, I'm not sure that it really tells you how to solve the issue properly.
Here's what I think you want, if each test instance should have a different d value in an instance variable:
class test(object): # new style class, since we inherit from "object"
_d = 0 # this is a class variable, which I've named _d to avoid confusion
def __init__(self):
self.d = test._d # assign current value of class variable to an instance variable
test._d += 1 # increment the class variable
Now, you can create multiple instances and each one will get a unique value for d:
>>> D0 = test()
>>> D1 = test()
>>> D2 = test()
>>> print D0.d
0
>>> print D1.d
1
>>> print D2.d
2
I am new to Python so please don't flame me if I ask something too noobish :)
1.
Consider I have a class:
class Test:
def __init__(self, x, y):
self.x = x
self.y = y
def wow():
print 5 * 5
Now I try to create an object of the class:
x = Test(3, 4)
This works as expected. However, when I try to call the method wow(), it returns an error, which is fixed by changing wow() to:
def wow(self)
Why do I need to include self and if I don't, what does the method mean?2. In the definition of __init__:
def __init__(self, x, y):
self.x = x
self.y = y
Why do I need to declare x and y, when I can do this:
def __init__(self):
self.x = x
self.y = y
I hope I am being clear...
Thanks for your time.
If you do that :
def __init__(self):
self.x = x
self.y = y
you assign the gobal vars x and y (it they exists ) to your instance
with :
def __init__(self, x, y):
self.x = x
self.y = y
you assign what you give as parameter to the constructor
and that is a lot more flexible :-)
The instance reference in Python is explicit. That way it can be manipulated by e.g. decorators before finally being passed to the method.
We need to declare x and y as arguments to the function so that we can use their names within the function, bound to the arguments passed in the corresponding function call.
Just to be clear
Why do I need to declare x and y, when
I can do this:
def __init__(self):
self.x = x
self.y = y
This ^ will only work if x and y can be found at runtime - if they haven't been passed in then they must have been set elsewhere (globally) or it will generate an error.
>>> class c:
def __init__(self):
self.x = x
>>> x = 1
>>> q = c()
>>> q.x
1
>>> del x
>>> q.x
1
>>> w = c()
Traceback (most recent call last):
File "<pyshell#24>", line 1, in <module>
w = c()
File "<pyshell#14>", line 3, in __init__
self.x = x
NameError: global name 'x' is not defined
>>>
>>> w = c(2)
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
w = c(2)
TypeError: __init__() takes exactly 1 argument (2 given)
This is why you want / need to specify them as parameters - it might work with the global lookup but it would probably violate the "principle of least astonishment"
self is a "magic" name - it can really be anything, but self is used for consistency and clarity. To answer your question, each class method/function requires an explicit reference to the class as the first parameter. Using Ipython:
In [66]: class Test:
....: def __init__(self):
....: pass
....: def wow(self):
....: print self
....:
....:
In [67]: x = Test()
In [68]: x.wow()
<__main__.Test instance at 0x0159FDF0>
Your second example won't actually work unless you already have an x and y in your namespace.
For instance, if you defined your class:
class Test:
def __init__(self):
self.x = x
self.y = y
and tried
x = Test()
it will throw a NameError.
However if you write:
x = 3
y = 4
test = Test()
then it will work. However, it's not a good idea to do such a thing. For the reason why read line 2:
In [72]: import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
In Python, methods should always take "one extra" argument, which is the reference to the instance the method is being called on. This is automatic in other languages such as Java, C#, etc. but Python is verbose about it.
That doesn't make sense. Where are x and y in that example? If you want the constructor to take two arguments which populate the object, define it as such. Otherwise, you're doing something else.
Python is different from languages like C++ and Java in that the object instance reference is passed explicitly.
That is, if you have an object which is an instance of the class and you want to invoke a method that operates on that instance (e.g., reads its fields), you use the self references as the object.
In c++ and Java, you have an implicit "this" reference that is present in the compiled version of your program but not in the source code. You use the static keyword to make it into a class method that does not have a "this".