Hi I am trying to use composition to create a new class using instances of another class when I try to turn the new object into a dictionary using __dict__, it's shows me <__main__.myobjec object at 0x00000000029CA908>, not sure am I using the __dict__ incorrectly though I have heard its related to new classes, any help greatly appreciated.
class User:
def __init__(self, name, job=None):
self.name = name
self.job = job
class Customer(User):
_ID = 100
def __init__(self, name, job=None):
self.name = name
self.job = job
class Account:
_ID = 0
def __init__(self, name, job=None):
self.customer = Customer(name , "Customer")
def __getattr__(self, attr):
return getattr(self.customer, attr)
>>> A = Account("Abdi")
>>> A.__dict__
{'customer': <__main__.Customer object at 0x109fdbfc8>}
>>>
You need to implement the __repr__ method to represent all of the instances of the Customer class.
def __repr__(self): return repr(self.__dict__) # the dictionary of attributes in __repr__
Related
I am trying to learn the difference between the instance attributes and class attributes and attributes. I have the code below and I am trying to distinguish these factors.
class Student:
firstname = ""
lastname = ""
ucid = ""
department = ""
nationality = ""
courses = {}
def __init__(self, fname, lname, ucid, dept, n):
self.firstname = fname
self.lastname = lname
self.ucid = ucid
self.department = dept
self.nationality = n
self.courses = {}
def setName(self, fname, lname):
self.firstname = fname
self.lastname = lname
def setDepartment(self, d):
self.department = d
def setUcid(self, u):
self.ucid = u
def setNationality(self, n):
self.nationality = n
def addCourse(self, coursename, gpa):
self.courses[coursename] = gpa
def printAll(self):
print("The name of the student is ", self.firstname, self.lastname)
print("nationality and UCID: ", self.nationality, self.ucid)
print("Department: ", self.department)
print("Result: ")
for key in self.courses.keys():
print(key, self.courses[key])
print("--------------------\n")
s1=Student("Beth","Bean","30303","Computer Science","International")
s1.addCourse("SCIENCE",3.75)
s1.printAll()
s2=Student("Mac","Miller","30303","Envr Science","American")
s2.addCourse("MATH",4.00)
s2.printAll()
From what I understood the attributes would be: firstname,lastname,ucid,department,nationality,courses But I do not know what instance attributes and class attributes would be.
I am trying to learn the difference between the instance attributes and class attributes and attributes.
there should be two attributes, class attribute, instance attribute. or instance attribute&none-instance attribute for convenience.
instance attribute
these are things activated only when __init__ has been called.
you can only access thenm after Class is initialized, which commonly seen as self.xxx.
and methods in class with self as its first parameter(normally), these functions are instance methods, and you can only access after you initialized the Class.
and methods in class with #property deco, they are instance attributes
common seen instance attribute
class Name(object):
def __init__(self):
self.age = 100
def func(self):
pass
#property
def age(self):
return self.age
class attribute
non-instance attribute or static attribute, whatever you call it
these things stay activated along with Class.
which means you can access them whenever you need to, like __init__, even in __new__.
they can be called by both Class and instance.
common seen class attribute
class Name(object):
attr = 'Im class attribute'
there is something else you may should know, class method, which stay activated along with Class but the difference is class method can't be called by instance but only Class. example here
class Name(object)
attr = 'Im class attribute'
#classmethod
def get_attr(cls):
return cls.attr
Conclusion
"class attribute" can be called by both instance and Class
"instance attribute" can only called by instance.
I have the following class structures:
class Parent(object):
def __init__(self, id, name):
self.id = id
self.name = name
def print_vars(self):
print(vars(self))
class Child(Parent):
def __init__(self, id, name, last_name, age):
Parent.__init__(self, id, name)
self.last_name = last_name
self.age = age
class AnotherChild(Parent):
def __init__(self, id, name, address):
Parent.__init__(self, id, name)
self.address= address
Perhaps not the best example, but I hope enough to get the idea accross. The idea is that I initialise two seperate instances that share some common attributes and methods. I need to be able to dump both objects into some json and csv files which I hope to achieve with the method dump_to_file (replaced by print_vars in this example). Now this method worked fine when I had to dump all the attributes from both the parent and child classes to a single file. Howeer, I want to only dump the attributes from the parent class. I tried to replace self by super or super(Parent, self) but without much success. What is the best way to access only the attributes from the class the code is written in?
I believe Java would do this automatically as the method is defined in the parent class, and the parent class does not know the child class attributes.
Assuming that you aren't going to add more variables outside __init__, you could freeze the list of variables in the __init__ method of the parent:
def __init__(self, id, name):
self.id = id
self.name = name
self.__parent_vars = dict(vars(self)) # make a copy
then use this dictionary, which has only the variables you defined when you initialized the parent class:
def print_values(self, path):
print(self.__parent_vars)
testing:
c = Child(12,"Foo","whatever",34)
c.print_vars()
I get:
{'id': 12, 'name': 'Foo'}
I face the same problem at current moment and trying to find solution.
#Jean-François Fabre♦ 's answer can't solve my own problem - it freezes arguments values at the moment of initializing Child class and if it change in future your Child class never knows about it.
I made some modifications to fix it:
class Parent(object):
def __init__(self, id, name):
self.id = id
self.name = name
self.__parent_vars = ['id', 'name'] # make a copy
def print_values(self):
res = {}
for el in self.__parent_vars:
res[el] = vars(self)[el]
return res
class Child(Parent):
def __init__(self, id, name, last_name, age):
Parent.__init__(self, id, name)
self.last_name = last_name
self.age = age
Lets test it:
c = Child(12,"Foo","whatever",34)
res1 = c.print_values()
print(res1)
c.id = 24
res2 = c.print_values()
print(res2)
Output:
{'id': 12, 'name': 'Foo'}
{'id': 24, 'name': 'Foo'}
Now it works as I expected BUT I need to create additioanl variable for it. So if I want to pickle, for example, my class it will also pickle this additional variable that I don't need. Is it possible to do the same actions qwithout creating additional variable?
I've created a class object called 'Node'. I then created two subclasses 'Beetle' and 'Dakota'. You'll notice there is an attr called 'superclass' which is part of the baseclass. I want this attribute to be set for each subclass and once it's set it should never be changed. It's a read-only attribute. I was wondering how to set this attribute up correctly in order to be a read only attribute?
class Node(object):
def __init__(self, name, superclass, attributes, children):
self.name = name
self.superclass = superclass
self.attributes = attributes if attributes is not None else {}
self.children = children if children is not None else []
class Beetle(Node):
def __init__(self, name="", superclass="Cars", attributes=None, children=None, enabled=True):
super(Beetle, self).__init__(name=name, superclass=superclass, attributes=attributes, children=children)
self.enabled = enabled
class Dakota(Node):
def __init__(self, name="", superclass="Trucks", attributes=None, children=None, enabled=True):
super(Dakota, self).__init__(name=name, superclass=superclass, attributes=attributes, children=children)
self.enabled = enabled
Rename you variable to add __ to the begining
self.__superclass = superclass
you can't access self.__superclass with something like Dakota().__superclass
if you want to get value of __superclass add a function in Node class to return it.
def getsuperclass(self):
return self.__superclass
...
Dakota().getsuperclass()
To have a 'read-only' property in a class you can make use of the #property decoration.
An example:
class Dakota(object):
def __init__(self, superclass):
self.__superclass = superclass
#property
def superclass(self):
return self.__superclass
Usage:
>>> a = Dakota('lol')
>>> a.superclass
'lol'
>>> a.superclass = 'hah'
AttributeError...
AttributeError: can't set attribute
You can refer to this other answer thread
I have a class Participant as follows:
class Participant:
def __init__(self,name,level):
self.name = name
self.level =level
I also have another class Team as follows:
class Team:
def __init__(self,name):
self.name = name
I want to create a method in the class Team to add an instance of class Participant; for instance:
Assume myTeam is an empty, valid instance of Team.
Also assume myParticipant1 is a valid instances of Participant
myTeam.addParticipant(participant= myParticipant1)
AddParticipant method should add the instance myParticipant1 to the instance myTeam.
How do I acheive it in Python?
Aside from the inheritance questions we're talking about in the comments, this is pretty simple stuff.
class Participant(object):
def __init__(self, name, level):
self.name = name
self.level = level
class Team(object):
def __init__(self, name):
self.name = name
self.participants = []
def add_participant(p):
self.participants.append(p)
DEMO:
my_team = Team("Monty Python")
p_info = [("Adam", 10e5), ("Joe-bob", -1)]
participants = [Participant(name, level) for name, level in p_info]
for participant in participants:
my_team.add_participant(participant)
# say that 10 times fast....
In [1]: [p.name for p in my_team.participants]
Out[1]: ["Adam", "Joe-bob"]
Is it possible to add a base class to an object instance (not a class!) at runtime? Something along the lines of how Object#extend works in Ruby:
class Gentleman(object):
def introduce_self(self):
return "Hello, my name is %s" % self.name
class Person(object):
def __init__(self, name):
self.name = name
p = Person("John")
# how to implement this method?
extend(p, Gentleman)
p.introduce_self() # => "Hello, my name is John"
This dynamically defines a new class GentlePerson, and reassigns p's class to it:
class Gentleman(object):
def introduce_self(self):
return "Hello, my name is %s" % self.name
class Person(object):
def __init__(self, name):
self.name = name
p = Person("John")
p.__class__ = type('GentlePerson',(Person,Gentleman),{})
print(p.introduce_self())
# "Hello, my name is John"
Per your request, this modifies p's bases, but does not alter p's original class Person. Thus, other instances of Person are unaffected (and would raise an AttributeError if introduce_self were called).
Although it was not directly asked in the question, I'll add for googlers and curiosity seekers, that it is also possible to dynamically change a class's bases but (AFAIK) only if the class does not inherit directly from object:
class Gentleman(object):
def introduce_self(self):
return "Hello, my name is %s" % self.name
class Base(object):pass
class Person(Base):
def __init__(self, name):
self.name = name
p = Person("John")
Person.__bases__=(Gentleman,object,)
print(p.introduce_self())
# "Hello, my name is John"
q = Person("Pete")
print(q.introduce_self())
# Hello, my name is Pete
Slightly cleaner version:
def extend_instance(obj, cls):
"""Apply mixins to a class instance after creation"""
base_cls = obj.__class__
base_cls_name = obj.__class__.__name__
obj.__class__ = type(base_cls_name, (base_cls, cls),{})
Although it's already answered, here is a function:
def extend(instance, new_class):
instance.__class__ = type(
'%s_extended_with_%s' % (instance.__class__.__name__, new_class.__name__),
(instance.__class__, new_class),
{},
)