In writing a Python (2.5) program, I tried to create a class and, in its __init__ function, automatically create an instance of another class with its name as an argument to the __init__ function, something like this:
class Class1:
def __init__(self,attribute):
self.attribute1=attribute
class Class2:
def __init__(self,instanceName):
#any of Class2's attributes
exec instanceName + '=Class1('attribute1')'
# this should produce an instance of Class1 whose name is instanceName
But when I make an instance of Class2, instance=Class2('instance2'), and try to get attribute1 of instance2 (which should have been created from Class2's __init__ function) I get an error message:
Traceback (most recent call last):
File "<pyshell#29>", line 1, in <module>
print instance2.attribute1
NameError: name 'instance2' is not defined
I don't know what the problem is, since name='instance3' and
exec name+'=Class1('attribute1') does work, though this is probably because I don't have much experience with Python. How would I be able to do something like this automatically when an instance is created?
I have to run, so hopefully, someone else can fix any mistakes in this post:
class Class1:
def __init__(self, attribute):
self.attribute1 = attribute
class Class2:
def __init__(self, instanceName):
setattr(self, instanceName, Class1(...)) # replace ... with whatever parameters you want
Related
I am very new to python : I want to serialize and deserialize my custom object in python. Please guide me on the same. I have a sample class :
import pickle
import json
class MyClass():
variable = "blah"
num = 10
def function(self):
print("this is a message inside the class.")
def get_variable():
return variable
def get_num():
return num
def main():
myObj = MyClass()
with open('/opt/infi/deeMyObj.txt', 'w') as output:
pickle.dump(myObj, output,pickle.HIGHEST_PROTOCOL)
with open('/opt/infi/deeMyObj.txt', 'r') as input:
myObjread = pickle.load(input)
print myObjread.get_variable()
print myObjread.get_num()
main()
I am getting following error :
Traceback (most recent call last):
File "sample.py", line 30, in
main()
File "sample.py", line 27, in main
print myObjread.get_variable()
TypeError: get_variable() takes no arguments (1 given)
Main intention is to read the object back.
To expand on jasonharper's comment, your get_variable and get_num methods aren't referring to the class's member variables. They should take the object as their first argument, e.g.
class MyClass:
...
def get_variable(self):
return self.variable
I think your serialization code is OK, but I might be wrong.
(Aside)
This is a bit off-topic, but another thing to note: when you define variables directly within the class block, they're defined on the class, not on objects of that class. That happens to work out in this case, since Python will look for a class-level variable of the same name if it can't find one on the object. However, if you store, say, a list in one of them and start modifying it, you'd end up sharing it between objects, which is probably not what you want. Instead you want to define them on in an __init__ method:
class MyClass:
def __init__(self):
self.variable = "blah"
During a lecture today we began to do work with subclasses within Python. As an example, we were given code resembling a very basic social network which is as follows:
class socialNetwork:
class node:
def __init__(self, name, friendList):
self.name=name
self.friendList=friendList
def __init__(self):
self.nodeList=[]
def addPerson(self, name, friendList):
person=self.node(name,friendList)
self.nodeList.append(person)
s = socialNetwork()
s.addPerson("John",["Alice","Bob"])
s.addPerson("Alice",["John","Bob","Jeff"])
s.addPerson("Bob",["John","Alice","Jeff","Ken"])
s.addPerson("Jeff",["Alice","Bob","Barbra"])
s.addPerson("Ken",["Bob","Barbra"])
s.addPerson("Barbra",["Jeff","Ken"])
for person in s.nodeList:
print("name: ",person.name, "\n\t friends: ",person.friendList)
However, whenever I attempt to run this, I receive the following message:
Traceback (most recent call last):
** IDLE Internal Exception:
File "C:\Users\Mike\AppData\Local\Programs\Python\Python36-
32\lib\idlelib\run.py", line 460, in runcode
exec(code, self.locals)
File "C:/Users/Mike/AppData/Local/Programs/Python/Python36-32/run.py",
line 15, in <module>
s.addPerson("John",["Alice","Bob"])
AttributeError: 'socialNetwork' object has no attribute 'addPerson'
Simply put, I have no idea why I am encountering this error, especially after the professor ran the same code just fine. Am I missing something here, and if so could someone please point it out?
Your class doesn't have addPerson method, because your class is indented wrong way. It should look like this:
class socialNetwork:
class node:
def __init__(self, name, friendList):
self.name=name
self.friendList=friendList
def __init__(self):
self.nodeList=[]
def addPerson(self, name, friendList):
person=self.node(name,friendList)
self.nodeList.append(person)
Indentation does matter in python. A clue that something is wrong would be you having two __init__ methods at the same level.
You haven't defined any subclasses. Inheritance is specified in Python by putting the parent class(es) in parenthesis, e.g.:
class Node:
pass
class Leaf(Node):
# Leaf is a subclass of Node
pass
"Network" and "Node" don't really make sense to be subclasses, but one should be composed of the other.
What you've done is define a class socialNetwork with one attribute, a class called node. That's why you get an AttributeError, because there is no addPerson attribute in socialNetwork.
Firstly, node is not a subclass of socialNetwork but a class nested within the latter.
Secondly, socialNetwork actually has no attribute addPerson, but socialNetwork.node does.
I'm not sure why this is happening. It seems to think that "self" requires an argument, which doesn't make any sense.
Here's my code:
class Animal:
def __init__(self):
self.quality = 1
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "bear.ppm"
class Fish(Animal):
def __init__(self):
Animal.__init__(self)
def getImage(self):
return "fish.ppm"
And the error I get is:
Traceback (most recent call last):
File "<pyshell#1>", line 1, in <module>
Bear.getImage()
TypeError: getImage() takes exactly 1 argument (0 given)
You have to instantiate Bear before you call getImage():
b = Bear()
b.getImage()
getImage is an instance method, so it is only designed to be called on a specific instance of the Bear class. The state of that instance is what is passed as the self variable to getImage. Calling b.getImage() is equivalent to this:
b = Bear()
Bear.getImage(b)
So, without an instance of Bear, there is nothing that can be used for the self argument, which is why you see that exception when you called Bear.getImage(). See the documentation on Python instance methods for more information.
If you want to be able to call getImage on the class Bear rather than on a specific instance, you need to make it a static method, using the #staticmethod decorator:
class Bear(Animal):
def __init__(self):
Animal.__init__(self)
#staticmethod
def getImage():
return "bear.ppm"
Then you could call Bear.getImage().
getImage() is an instance method, so it can only be called with a instantiation of Bear class. So here is how you can do it:
Bear().getImage()
or
be = Bear()
be.getImage()
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'