I have a problem with list within a class in python. Here's my code :
class Residues:
def setdata(self, name):
self.name = name
self.atoms = list()
a = atom
C = Residues()
C.atoms.append(a)
Something like this. I get an error saying:
AttributeError: Residues instance has no attribute 'atoms'
Your class doesn't have a __init__(), so by the time it's instantiated, the attribute atoms is not present. You'd have to do C.setdata('something') so C.atoms becomes available.
>>> C = Residues()
>>> C.atoms.append('thing')
Traceback (most recent call last):
File "<pyshell#84>", line 1, in <module>
B.atoms.append('thing')
AttributeError: Residues instance has no attribute 'atoms'
>>> C.setdata('something')
>>> C.atoms.append('thing') # now it works
>>>
Unlike in languages like Java, where you know at compile time what attributes/member variables an object will have, in Python you can dynamically add attributes at runtime. This also implies instances of the same class can have different attributes.
To ensure you'll always have (unless you mess with it down the line, then it's your own fault) an atoms list you could add a constructor:
def __init__(self):
self.atoms = []
the error means the class Residues doesn't have a function call atoms. The solution could be as follows:
class Residues:
def setdata(self, atoms, name=None):
self.name = name
self.atoms =[]
C = Residues()
C.setdata(atoms= " a ")
Related
Given a class Mitarbeiter with the constructor __init__ which is creating 3 variables. Can additional variables be added by another method in python? Example below:
class Mitarbeiter:
species = "Homo sapiens"
#Klassenmethoden ändern nur Klassenattribute
#statische Methoden verwenden werder Instanz- noch Klassenattribute
#konstruktor
def __init__ (self, vorname, name, personalnummer):
self.__vorname = vorname
self.__name = name
self.__personalnummer = personalnummer
def _def_abteilung(self, abteilung):
self.__abteilung = abteilung
def _set_vorgesetzter (self, vorgesetzter):
self.__vorgesetzer = vorgesetzter
#property
def get_abteilung(self,):
return self.__abteilung
when I create an Object of Mitarbeiter with the variables vorname, name and personalnummer I can call later the method _def_abteilung to set some more information to the Object Mitarbeiter.
ma1 = Mitarbeiter("Franz", "Bauer", 736) #--> Works
ma1._def_abteilung("Test") #--> Works
ma1.abteilung #--> does not work, any Ideas?
The "_name is private" convention is a convention (privacy isn't enforced in any way),
"__name" mangles the name so ma1.__abteilung literally doesn't exist outside the class.
See What is the meaning of single and double underscore before an object name? and Python Name Mangling and How to Use Underscores
You can set attributes for an object anywhere -- if you changed self.__abteilung to self.abteilung, that name wouldn't be mangled by the interpreter and you would see the abteilung attribute defined on all Mitarbeiter objects.
Consider the following TestClass example:
class TestClass:
def __init__(self, a):
self.a = a
def set_b(self, b):
self.b = b
def set_mangled(self, m):
self.__m = m
print("Mangled", self.__m)
def get_mangled(self):
return self.__m
The a attribute is set in the __init__, so t.a always exists
t = TestClass(0)
print(t.a) # 0
print(t.b) # AttributeError
The b attribute is only set in the set_b method, so it only exists on an object after that method is called. The method can set an attribute of the object using the reference self. Trying to print t.b before setting it throws an AttributeError
t.set_b(10)
print(t.a) # 0
print(t.b) # 10
print(t.c) # AttributeError
The c attribute is set only once you run the line t.c = 100. As you can see, it is possible to set the attribute from outside the class. Trying to access t.c before setting it throws an AttributeError.
t.c = 100
print(t.a) # 0
print(t.b) # 10
print(t.c) # 100
The __m attribute is defined as a mangled name. Inside the class, it is accessed using self.__m. Outside the class, the name is mangled to _TestClass__m, so it is not accessible as t.__m or t.m.
t.set_mangled(1000) # Mangled: 1000
print(t.get_mangled()) # 1000
print(t._TestClass__m) # 1000
print(t.__m) # AttributeError: 'TestClass' object has no attribute '__m'
print(t.m) # AttributeError: 'TestClass' object has no attribute 'm'
Let's say we have this simple Python code
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
Correct me if I get any of this wrong:
Class_Var is a class variable that is the same for all instances of MyClass object.
I_Var is an instance variable that only exists in instances of the MyClass object
foo = MyClass(2)
bar = MyClass(3)
foo.class_var, foo.i_var
## 1, 2
bar.class_var, bar.i_var
## 1, 3
Class variables are also properties of the class itself.
MyClass.class_var ##
## 1
MyClass.I_var should error out, correct?
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
MyClass.new_attribute = 'foo'
print(hasattr(ObjectCreator, 'new_attribute'))
That should return true. And
print (MyClass.new_attribute)
should return foo.
How come we can create a new class variable that was not defined in the original definition for that class?
Is
MyClass.new_attribute = 'foo'
the exact same thing as creating that class attribute in the original definition?
class MyClass(object):
class_var = 1
new_attribute = 'foo'
So we can create new class attributes at runtime? How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
A class object is just an instance of yet another type, usually type (though you can change this using the metaclass parameter to the class statement).
Like most other instances, you can add arbitrary instance attributes to a class object at any time.
Class attributes and instance attributes are wholly separate; the former are stored on the class object, the latter on instances of the class.
There's nothing particularly special about __init__; it's just another method that, among other things, can attached new attributes to an object. What is special is that __init__ is called automatically when you create a new instance of the class by calling the class. foo = MyClass(2) is equivalent to
foo = MyClass.__new__(MyClass, 2)
foo.__init__(2)
The class statement
class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
is roughly equivalent to
def my_class_init(self, i_var):
self.i_var = i_var
MyClass = type('MyClass', (object,), {'class_var': 1, '__init__: my_class_init})
The 3-argument form of type lets you pass a dict that creates class attributes when you first create the class, but you can always assign attributes after the fact as well:
MyClass = type('MyClass', (object,), {})
MyClass.class_var = 1
MyClass.__init__ = my_class_init
Just to blow your mind a little bit more, the call to type can be though of as
MyClass = type.__new__(type, 'MyClass', (object,), {...})
MyClass.__init__('MyClass', (object,), {...})
though unless you define a custom metaclass (by subclassing type), you never have to think about type itself having __new__ and __init__ methods.
Does that mean that class variables can be considered like instance variables of the class object itself (since all classes are objects) ?
Yes.
How come we can create a new class variable that was not defined in the original definition for that class?
Because Python is a dynamic language. A class can be created at run time - in fact, it is created at run time when you run Python interactively.
So we can create new class attributes at runtime?
Yes, unless the metaclass (the class of the class) has forbidden it.
How does that not interfere with the init constructor that creates the class object and has those class variables as instance variables of the class object?
The only rule is that you cannot use something that has not yet be defined or something that has been deleted:
>>> class MyClass(object):
class_var = 1
def __init__(self, i_var):
self.i_var = i_var
self.j_var = self.class_var + 1
>>> a = MyClass(2)
>>> del MyClass.class_var
>>> b = MyClass(3)
Traceback (most recent call last):
File "<pyshell#39>", line 1, in <module>
b = MyClass(3)
File "<pyshell#36>", line 6, in __init__
self.j_var = self.class_var + 1
AttributeError: 'MyClass' object has no attribute 'class_var'
There is no magic here: anything can only exists between its definition point and its destruction point. Python allows you to add attributes to objects at any time, except that some classes (for example object) forbid it.
With the previous a object of class MyClass, you could do:
a.z_var = 12
from that point, z_var will be an attribute of a but others objects of same class will not have it.
Simply object forbids that:
>>> o = object()
>>> o.x=1
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
o.x=1
AttributeError: 'object' object has no attribute 'x'
I have a simple class A that gets the name from users.
class A:
def __init__(self, name = ''):
self.name = name
Then I want to create a class B that prints out this name. I tried:
class B:
def print_name(printing_name = A.name):
print(printing_name)
Then I call these methods:
m1 = A("x")
B.print_name(m1)
This returns the error
Traceback (most recent call last):
File "so.py", line 5, in <module>
class B:
File "so.py", line 7, in B
def print_name(printing_name = A.name):
AttributeError: class A has no attribute 'name'
I know that I did not assign a class variable in the class A, and thus the name attribute goes with specific instances, not the entire class. However, the name attribute has to connect with every specific instance because it changes from the case to case. Then how should I get this name in class B?
Change your class B to this:
class B:
#staticmethod
def print_name(obj):
print(obj.name)
The print_name method probably should be decorated as a "static method". The property "name" of self is an instance attribute which can not be referred directly from the class itself.
That's correct: name is an instance attribute, not a class attribute. IN this case, m1 has a name, but class A does not. You need to access the name of the input parameter, not attempt to print a class attribute.
You also need to make B.print_name a class function, since you're not calling it from an instance of B.
class B:
#staticmethod
def print_name(inst):
print(inst.name)
Output:
x
Edit: The answers suggesting #staticmethod are ideal if you understand what it does.
class A:
def __init__(self, name = ''):
self.name = name
class B:
def __init__(self):
pass
def print_name(self, var):
print (var.name)
Output:
>>> m1 = A("X")
>>> b = B()
>>> b.print_name(m1)
X
>>>
In this instance A is the name of the class, and you should not give it as the default argument for calling the print_name method. Have a look at keyword arguments for Python, and you will see that what you have written actually means that you have the default value set to the .name property of the class A, which does not exist unless the class is instantiated (i.e. an object is created of the class).
Your B class should read:
class B:
def print_name(printing_object):
print(printing_object.name)
I want to define an attribute in a method:
class variables:
def definition(self):
self.word = "apple"
Then I want to use the defined attribute:
test = variables()
print test.definition.word
Instead of writing 'apple' I get an error:
Traceback (most recent call last):
File "bezejmenný.py", line 6, in <module>
print test.definition.word
AttributeError: 'function' object has no attribute 'word'
definition is a method so you need to execute it
Because you are assigning a variable to self, you can access it through your instance as follows
test = variables()
test.definition()
print test.word
A few ideas:
It's best practice start class names with a capital letter
If you just want you class to have a field, you don't need your definition method
Extend your class with object because everything in python is objects (python 2.x only)
class Variables(object):
def __init__(self):
self.word = 'I am a word'
variables = Variables()
print variables.word
You can access instance attribute like this:
test = variable()
test.definition()
print test.word
Assume that I have a class as following:
class MyClass(object):
def __init__(self, value=None):
self.attr = value
#property
def attr(self):
# This acts as a getter?
# Let's call the function "attr_1" as alias
return self.__attr
#attr.setter
def attr(self, value):
# This acts as a setter?
# Let's call the function "attr_2" as alias
self.__attr = value
inst = MyClass(1)
I read the Documentation on Descriptor and looked at the implementation of property class.
As far as I know, when I type inst.attr, the following happens:
The first attr (whose alias is attr_1) is found, and attr is now an instance of property class, which is a data descriptor.
Therefore, it will override the instance dictionary, which means type(inst).__dict__['attr'].__get__(inst, type(inst)) is invoked.
attr.__get__(inst, type(inst)) invokes attr.fget(inst), where fget() is in fact the attr(self) (the "raw" attr_1 function).
Finally, attr.fget(inst) returns inst.__attr.
Here comes the first question: the class MyClass does not have an attribute __attr, then how to interpret inst.__attrin step 3?
Similarly, in the emulated setter, how does Python find an attribute inst.__attr to assign the value?
And a trivial question: since property is a class, why not Property instead of property?
Your question is not directly related to properties actually, and the way they work as data descriptors. It's just the way Python fakes private attributes marked as starting with two underscores.
>>> inst.__attr
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
inst.__attr
AttributeError: 'MyClass' object has no attribute '__attr'
Consider that you wrote your code using an internal variable with a single underscore (usually the convention to say, you shouldn't touch this but I won't enforce, do at your own risk):
>>> class MyClass2(object):
def __init__(self, value=None):
self.attr = value
#property
def attr(self):
# This acts as a getter?
# Let's call the function "attr_1" as alias
return self._attr
#attr.setter
def attr(self, value):
# This acts as a setter?
# Let's call the function "attr_2" as alias
self._attr = value
>>> inst2 = MyClass2(1)
>>> inst2._attr
1
And you can see the trick by peeking at the object's __dict__
>>> inst2.__dict__
{'_attr': 1}
>>> inst.__dict__
{'_MyClass__attr': 1}
Just some more to convince you that this has nothing to do with properties:
>>> class OtherClass(object):
def __init__(self, value):
self.__attr = value
def get_attr(self):
return self.__attr
def set_attr(self, value):
self.__attr = value
>>> other_inst = OtherClass(1)
>>> other_inst.get_attr()
1
>>> other_inst.__attr
Traceback (most recent call last):
File "<pyshell#17>", line 1, in <module>
other_inst.__attr
AttributeError: 'OtherClass' object has no attribute '__attr'
>>> other_inst.__dict__
{'_OtherClass__attr': 1}
>>> other_inst._OtherClass__attr
1
>>> other_inst._OtherClass__attr = 24
>>> other_inst.get_attr()
24
>>> inst._MyClass__attr = 23
>>> inst.attr
23
Concerning your last question, I just don't think there is such a convention in Python that classes must start with an uppercase. property is not an isolated case (datetime, itemgetter, csv.reader, ...).