I'm having a python problem with a simple program. The program is supposed to allow the user to make a make a Cow() instance and give the cow a name in the parameter.
class Cow():
def __init__(self, name):
self.name = name
if self.name == None:
raise NoNameCowError("Your cow must have a name")
def speak(self):
print self.name, "says moo"
Now when I do
cow.Cow("Toby")
I get the error
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
cow.Cow("Toby")
File "C:\Users\Samga_000\Documents\MyPrograms\cow.py", line 8, in __init__
self.name = name
AttributeError: Cow instance has no attribute 'name'
Help? I originally thought I did something wrong with the exception but it doesn't seem to be that. Thanks in advance.
I think you modified your source code and didn't reloaded the module:
Buggy version:
class Cow():
def __init__(self, name):
if self.name == None:
raise NoNameCowError("Your cow must have a name")
def speak(self):
print self.name, "says moo"
>>> import so
Error raised as expected:
>>> so.Cow('abc1')
Traceback (most recent call last):
File "<ipython-input-4-80383f90b571>", line 1, in <module>
so.Cow('abc1')
File "so.py", line 3, in __init__
if self.name == None:
AttributeError: Cow instance has no attribute 'name'
Now let's modify the source code and add this line self.name = name:
>>> import so
>>> so.Cow('abc1')
Traceback (most recent call last):
File "<ipython-input-6-80383f90b571>", line 1, in <module>
so.Cow('abc1')
File "so.py", line 3, in __init__
self.name = name
AttributeError: Cow instance has no attribute 'name'
eh! still same error? That's because python is still using the old .pyc file or the cached module object. Just reload the module and updated code works fine:
>>> reload(so)
<module 'so' from 'so.py'>
>>> so.Cow('dsfds')
<so.Cow instance at 0x8b78e8c>
From docs:
Note For efficiency reasons, each module is only imported once per
interpreter session. Therefore, if you change your modules, you must
restart the interpreter – or, if it’s just one module you want to test
interactively, use reload(), e.g. reload(modulename).
A better version of your code:
class Cow():
def __init__(self, name=None): #Use a default value
self.name = name
if self.name is None: #use `is` for testing against `None`
raise NoNameCowError("Your cow must have a name")
I'm staring at the name check; this object requires the name argument does it not?
if self.name == None:
raise NoNameCowError("Your cow must have a name")
I'm a little Python thick, but that looks like a required arg.
When your declaring Cow, you need to pass object in the parentheses:
class Cow(object):
rest of code.
This way Python knows the class your declaring is an object with attributes and methods.
Related
I faced with this problem in my work code, so I can't show it. But I wrote some short example, which exactly reproduce error and cuts off redundant logic.
Example have two files: Example.py & ImportedExample.py.
Example.py
from multiprocessing import Process
from ImportedExample import Imported
class Example:
def __init__(self, number):
self.imported = Imported(number)
def func(example: Example):
print(example)
if __name__ == "__main__":
ex = Example(3)
p = Process(target=func, args=(ex,))
p.start()
ImportedExample.py
class Imported:
def __init__(self, number):
self.number = number
self.ref = self.__private_method
def __private_method(self):
print(self.number)
And Traceback looks like this:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File"C:\Python\Python36\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "C:\Python\Python36\lib\multiprocessing\spawn.py", line 115, in _main
self = reduction.pickle.load(from_parent)
AttributeError: 'Imported' object has no attribute '__private_method'
The main detail is that when I make __private_method() non-private (renaming to private_method()), all works fine.
I don't understand why this happens. Any suggestions?
multiprocessing module uses pickle for transferring object between processes.
For an object to be pickable, it has to be accessible by name. Thanks to private name mangling, referenced private methods don’t fall in that category.
I suggest making the method protected – that is naming the method with only one leading underscore. From a global point of view, protected methods shoud be treated just as private methods, but they are not subject of name mangling.
Using python 2.7
I'm creating a library of objects on import using decorators, and while importing I do some checks on the instance of each object; mostly duplication checks...
I've recently made the switch to using super() to take advantage of its multiple-inheritance handling, but it raises a NameError on the object being instantiated.
Simplified code highlighting issue:
class Lib(object):
def __init__(self):
print "library created"
self.lib = {}
def add_obj(self, obj):
print "object being added to library --> %s" % obj.__name__
inst = obj()
print inst.name
self.lib[obj.__name__] = obj
def Reg(obj):
global test_lib
test_lib.add_obj(obj)
test_lib = Lib()
#Reg
class A(object):
def __init__(self):
object.__init__(self)
self.name = "A instance"
#Reg
class B(object):
def __init__(self):
super(B, self).__init__()
self.name = "B instance"
Output
>>> from testing import *
library created
object being added to library --> A
A instance
object being added to library --> B
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "testing.py", line 25, in <module>
class B(object):
File "testing.py", line 14, in Reg
test_lib.add_obj(obj)
File "testing.py", line 8, in add_obj
inst = obj()
File "testing.py", line 27, in __init__
super(B, self).__init__()
NameError: global name 'B' is not defined
It seems like there's a scoping issue? Excluding the decorator, class B instantiates without a problem.
Any suggestions?
You are attempting to instantiate B before it has finished being defined.
Fix it:
Remove these lines from Lib.add_obj():
inst = obj()
print inst.name
Why?
The decorator Reg is involved in the definition of B. So you will not be able to instantiate B, via that name, until Reg has exited.
I defined an instance variable in the init() method of a class and derived a new class from it. When I try to reference this variable from an instance of the secondary class, it seems it was not inherited.
This is the code:
company=Company()
person=Person()
task=Task()
print(company.get_attrs())
class Entity(Persistent):
list_of_attrs=[]
list_of_attrs_flag=False
def __init__(self):
attributes={}
attributes_edition_flag={}
if not type(self).list_of_attrs_flag:
type(self).list_of_attrs=self.get_attrs_from_persistent()
type(self).list_of_attrs_flag=True
for attr in type(self).list_of_attrs:
attributes[attr]=''
attributes_edition_flag[attr]='false'
def get_attrs(self):
return(self.attributes)
class Company(Entity):
def hello(self):
print('hello')
This is the error I get:
MacBook-Pro-de-Hugo:Attractora hvillalobos$ virtual/bin/python3 control.py
Traceback (most recent call last):
File "control.py", line 7, in <module>
print(company.get_attrs())
File "/Users/hvillalobos/Dropbox/Code/Attractora/model.py", line 48, in get_attrs
return(self.attributes)
AttributeError: 'Company' object has no attribute 'attributes'
It was working but I moved something (I guess), but I can't find what.
Thanks for your help
In your __init__ method, you have to use self.attributes, not attributes.
Given below is a snippet from a class of which I am trying to create objects and getting error:
class FoF(object):
def __init__(self,path):
filepath=[]
filepath.append(self.FileOrFolder(path))
Upon executing which I get the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "PathOps.py", line 6, in __init__
def __init__(self,path):
NameError: global name 'filepath' is not defined
After which I tried:
filepath=[]
class FoF(object):
def __init__(self,path):
global filepath.append(self.FileOrFolder(path))
And again:
File "<stdin>", line 1, in <module>
File "PathOps.py", line 6, in __init__
global filepath.append(self.FileOrFolder(path))
NameError: global name 'filepath' is not defined
What is causing the error and how do I fix it?
Try using insted of global the special word self.
So something like this
class FoF(object):
def __init__(self,path):
self.filepath=[]
self.filepath.append(self.FileOrFolder(path))
The reason this error comes up is because what python thinks you're trying to do is one of two things:
Either you're trying to reference a global variable called filepath -- which is clear that's not what you're trying
What's not so clear is that you could also define a class attribute called filepath -- the only problem with that is that you can't define a class attribute with a function of that class. You can only do so within the class -- outside a class function
So in order to declare variables within a function you have to use the word self before it.
Edit** if you want it to be an attribute of the class -- as I'm assuming is what you meant you could do so like this:
class FoF(object):
filepath=[]
def __init__(self,path):
self.filepath.append(self.FileOrFolder(path))
I don't think you're giving us enough information. For example:
>>> class FoF(object):
... def __init__(self, path):
... junk = []
... junk.append(path)
...
>>> foo = FoF('bar/path')
produces no error.
What, exactly, are you trying to do?
If I have a python class, how can I alias that class-name into another class-name and retain all it's methods and class members and instance members? Is this possible without using inheritance?
e.g. I have a class like:
class MyReallyBigClassNameWhichIHateToType:
def __init__(self):
<blah>
[...]
I'm creating an interactive console session where I don't want my users' fingers to fall off while instantiating the class in the interactive sessions, so I want to alias that really long class name to something tiny like 'C'. Is there an easy way to do this without inheritance?
C = MyReallyBigClassNameWhichIHateToType
Also, if you're importing the name from another module...
from modulename import ReallyLongNameWhichIHateToType as FriendlyName
You can simply do:
ShortName = MyReallyBigClassNameWhichIHateToType
A class in Python is just an object like any other, and can have more than one name.
Refactor the name, no reason it should have a name that long.
Otherwise whateverName = VeryLongClassName should do the trick.
Simple name assignment approach works but has one disadvantage that might be important in some cases: the alias name will be the same as the name of the "base" class because of the __name__ property.
class C(object):
pass
D = C
print(C.__name__) # 'C'
print(D.__name__) # 'C' again
For example, if you create custom exception and then another one that assigning the first one you will get the name of this "parent" exception every time no matter which one of them you raise and this should probably confuse a user:
class CustomBaseException(Exception):
def __init__(self, operation):
super(CustomBaseException, self).__init__()
self.operation = operation
def __str__(self):
return f"Invalid operation '{self.operation}'"
OperationException = CustomBaseException
raise OperationException('readd')
output:
Traceback (most recent call last):
File "<input>", line 12, in <module>
CustomBaseException: Invalid operation 'readd'
So a solution would be to actually subclass the class:
class CustomBaseException(Exception):
def __init__(self, operation):
super(CustomBaseException, self).__init__()
self.operation = operation
def __str__(self):
return f"Invalid operation '{self.operation}'"
class OperationException(CustomBaseException):
pass
raise OperationException('delite')
output:
Traceback (most recent call last):
File "<input>", line 14, in <module>
OperationException: Invalid operation 'delite'