I'm trying to modify class attribute by reference to object in __init__ method and then use it in another method. Sadly the following code sample doesn't work as expected...
CODE
class Translator:
#list of attributes
parser=None
def __init__(self):
parser = Parser_class() ...
#some other commands
def Translate(self):
something=self.parser.GenerateHead() ...
#more commands
COMPILE ERR
AttributeError: 'NoneType' object has no attribute 'GenerateHead'
I know that I can give it to the Translate method as argument, I'm just curious why this statement within Python doesn't work.
You're doing your instance attributes wrong.
First off, you don't need to declare your attributes ahead of time. Putting parser = None at the top level of the class creates a class variable named parser, which I don't think is what you want. Usually in Python you can add new instance attributes at any time by a simple assignment: instance.attr = "whatever".
Second, when you want to do an instance assignment from within a method, you need to use self to refer to the instance. If you leave off self, you'll be assigning to a local variable inside your function, not to an instance or class variable. Actually, the specific name self isn't necessary, but you do need to use the first argument to the method (and it's probably not a good idea to break the convention of naming that self).
So, to fix your code, do this:
class Translator:
# don't declare variables at class level (unless you actually want class variables)
def __init__(self):
self.parser = Parser_class() # use self to assign an instance attribute
def Translate(self):
something = self.parser.GenerateHead() # this should now work
Related
I don't understand why this works;
class parentClass(object):
pass
class childClass(parentClass):
def my_meth(var):
print(var)
a = {'meth': my_meth}
x = childClass.a['meth']("Helloworld")
Whilst this fails;
class parentClass(object):
pass
class childClass(parentClass):
a = {'meth': my_meth}
def my_meth(var):
print(var)
x = childClass.a['meth']("Helloworld")
It would seem that a class is read line by line on execution and if the method definition has not been parsed before it is referenced within an attribute, an error occurs?
Is this true? Why does this occur in class/static attributes whilst you can def methods in any order and reference them from other methods written above or below them?
Is there a way to keep the class attributes at the top of the class to preserve readability and consistent layout?
It would seem that a class is read line by line on execution and if the method definition has not been parsed before it is referenced within an attribute, an error occurs?
Yes, that is true. Class definitions are executed from top to bottom, just like module-level code. You can even put things like if/else statements and for loops directly inside the class body.
Is there a way to keep the class attributes at the top of the class to preserve readability and consistent layout?
Your first example is fine. The order is not considered strange in Python.
That said, you do have potential alternatives. You could, for example, create a #classmethod to initialize class attributes at the top of the class, and then call immediately after the class declaration, e.g.
class childClass(parentClass):
#classmethod
def _initialize(cls)
cls.a = {'meth': cls.my_meth}
def my_meth(var):
print(var)
childClass._initialize()
You could even write a class decorator to do this step for you (if you think that's prettier), as they execute after the class declaration code has completed execution.
Why does this occur in class/static attributes whilst you can def methods in any order and reference them from other methods written above or below them?
Executing a function definition is different from calling the function object it creates. The former just creates the function object and assigns its name to the local context. The latter runs its code.
Classes are just fancy dicts. You can swap attributes in and out of them at runtime. When you do a self.foo() inside of a method bar, the . operator is doing an attribute lookup of the foo attribute on the self object. It's a similar idea when using cls.foo() in a classmethod.
It's entirely possible to write a function that references an attribute that doesn't exist. It will fail with an AttributeError, of course, if you call it, but if somehow the attribute gets set later, then you can call it successfully.
I am trying to make a class within a module, import that module file in my controller, and then reference the class that is defined within that module, but I keep getting a message that reads NameError("name 'self' is not defined")
Here is my code in my created module:
from gluon import *
class device_info(object):
self.info = {}
def __init__(self, info):
self.info = info
return
def setInfo(info):
self.info = info
return
def getInfo():
return self.info`
Does anyone know what causes this and how it can be resolved? I was under the impression that user-defined classes were supported in web2py.
As stated, just move self.info = {} into __init__().
__init__() is essentially a constructor that you are familiar with from java. It initializes an instance object of that class when called. I haven't used Java in some time, but I don't think you should be be declaring class variables outside of your constructor there either.
self is an argument that all methods within a class in python must receive as their first argument. So your getters and setters are also not going to work if you try them; they must be:
def setInfo(self, info) and def getInfo(self)
When you create an object, like this:
device1 = device_info()
it calls __init()__, passing device1 as self. Then, whenever you use that object, such as
device1.setInfo(newInfo), you can think of the method in the class' context being called as setInfo(device1, newInfo), since device1 is self, or the current instance of the device_info object in use.
You also don't need the object argument at the class definition. What do you expect that to do?
Edit: Actually, don't move self.info = {} into __init__(), just get rid of it. You already have self.info = info in __init__(). You don't need to initialize variables like that in Python like you do in Java. Creating an empty dict and then setting it to another dict without any use is redundant.
here is a part of my code :
class projet(object):
def nameCouche(self):
valLissage = float(ui.valLissage.displayText())
return (valLissage)
valCouche = nameCouche() # asks for a positional argument but 'self' doesnt work
def choixTraitement(self):
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self, valCouche):
if ui.chkboxLissage.isChecked():
print(valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(valCouche))
So I would like to use valCouche in goLissage method but it doesnt work.
I thought that valCouche would have the argument of valLissage but instead it gives False as a value.
I've tried different alternatives but still doesnt work.
You've got multiple problems here.
First, if you write this in the middle of a class definition:
valCouche = nameCouche()
... you're creating a class attribute, which is shared by all instances, not a normal instance attribute.
Also, you're running this at class definition time. That means there is no self yet--there aren't any instances yet to be self--so you can't call a method like nameCouche, because you don't have anything to call it on.
What you want to do is call the method at instance initialization time, on the instance being initialized, and store the return value in an instance attribute:
def __init__(self):
self.valCouche = self.nameCouche()
Then, when you want to access this value in another method later, you have to access it as self.valCouche.
If you make those changes, it will work. But your object model still doesn't make much sense. Why is nameCouche a method when it doesn't have anything to do with the object, and doesn't access any of its attributes? Maybe it makes sense as a #staticmethod, but really, I think it makes more sense just as a plain function outside the class. In fact, none of the code you've written seems to have anything to do with the class.
This kind of cram-everything-into-the-class design is often a sign that you're trying to write Java code in Python, and haven't yet really understood how Python does OO. You might want to read a good tutorial on Python classes. But briefly: if you're writing a class just to have somewhere to dump a bunch of vaguely-related functions, what you want is a module, not a class. If you have some reason to have instances of that class, and the functions all act on the data of each instance, then you want a class.
You have to declare variabile in the __init__ method (constructor) and then use it in your code
ex:
class projet(object):
def __init__(self):
self.valCouche = ''
def nameCouche(self):
valLissage = float(ui.valLissage.displayText())
return (valLissage)
def choixTraitement(self):
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self, valCouche):
if ui.chkboxLissage.isChecked():
self.valCouche = self.nameCouche()
print(self.valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(self.valCouche))
you have to define an initialization function: def__init__(self)
defining valCouche as an instance attribute make it accessible on all the method so we have the following
class projet(object):
def __init__(self):
self.valCouche = ''
def nameCouche(self):
self.valCouche = float(ui.valLissage.displayText())
#staticmethod #here there is no need for self so it is a method of class
def choixTraitement():
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self):
if ui.chkboxLissage.isChecked():
print(self.valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(self.valCouche))
While researching about python class attribute and instance attribute, I came to know that it's not possible to create object attribute outside object methods (or may be class method). Like code below will generate an "NameError" in python.
class test(object):
def __init__(self):
self.lst = []
self.str = 'xyz'
Why python doesn't allow this? I'm not questioning language creator's decision, but any reason behind this. Like, is it technically incorrect or any other disadvantage of this behavior.
You are defining a class, so there is no instance to point to outside methods. Drop the `self:
class test(object):
def __init__(self):
self.lst = []
str = 'xyz'
self points to the instance, not the class. You either need to create an instance and assign directly to attributes (test().str = 'xyz') or you need to be inside a method (when self can actually refer to an instance).
self is not a special name in python, you could use \
class test(object):
def __init__(foo):
foo.lst = []
If you want. Every method of a class gets the instance explicitly passed to it as the first parameter, you can call it whatever you want. Trying to access a parameter outside the scope of the method obviously won't work.
When I write class in python, most of the time, I am eager to set variables I use, as properties of the object. Is there any rule or general guidelines about which variables should be used as class/instance attribute and which should not?
for example:
class simple(object):
def __init(self):
a=2
b=3
return a*b
class simple(object):
def __init(self):
self.a=2
self.b=3
return a*b
While I completely understand the attributes should be a property of the object. This is simple to understand when the class declaration is simple but as the program goes longer and longer and there are many places where the data exchange between various modules should be done, I get confused on where I should use a/b or self.a/self.b. Is there any guidelines for this?
Where you use self.a you are creating a property, so this can be accessed from outside the class and persists beyond that function. These should be used for storing data about the object.
Where you use a it is a local variable, and only lasts while in the scope of that function, so should be used where you are only using it within the function (as in this case).
Note that __init is misleading, as it looks like __init__ - but isn't the constructor. If you intended them to be the constructor, then it makes no sense to return a value (as the new object is what is returned).
class Person(object):
def __init__(self, name):
# Introduce all instance variables on __init__
self.name = name
self.another = None
def get_name(self):
# get_name has access to the `instance` variable 'name'
return self.name
So if you want a variable to be available on more than one method, make
it an instance variable.
Notice my comment on introducing all instance vars on __init__.
Although the example below is valid python don't do it.
class Person(object):
def __init__(self):
self.a = 0
def foo(self):
self.b = 1 # Whoa, introduced new instance variable
Instead initialize all your instance variables on __init__ and set
them to None if no other value is appropriate for them.
I try to imagine what I want the API of my class to look like prior to implementing it. I think to myself, If I didn't write this class, would I want to read the documentation about what this particular variable does? If reading that documentation would simply waste my time, then it should probably be a local variable.
Occasionally, you need to preserve some information, but you wouldn't necessarily want that to be part of the API, which is when you use the convention of appending an underscore. e.g. self._some_data_that_is_not_part_of_the_api.
The self parameter refers to the object itself. So if you need to use on of the class attributes outside of the class you would it call it as the name of class instance and the attribute name. I don't think there is any guideline on when to use self, it all depends on your need. When you are building a class you should try to think about what you will use the variables you creating for. If you know for sure that you will need that specific attribute in the program you are importing your class, then add self.