I have a list of objects of the Person class. This list includes myself, so I need to remove "myself" from the list.
It means I need to remove the object from the list that calls this method.
class Population:
def __init__(self):
self.people = list()
class Person:
def __init__(self):
self.friends_list = list()
def make_friends(self, population, n):
temp_list = population.copy()
temp_list.remove(self)
self.friends_list.extend(random.sample(temp_list,n))
my test:
per = Person()
per2 = Person()
per3 = Person()
per4 = Person()
per5 = Person()
pop = [per,per2,per3,per4,per5]
for per in pop:
per.make_friends(pop, 2)
print('ME: ',per)
print(per.friends_list)
My tests run well, but there are general tests that check the code and they generate an error on this line:
try:
stud_res = person.make_friends(population, count)
except Exception:
print("\tPerson.make_friends() generated error")
return
Can I use self in this way, and if not, how can I better remove "myself" from the list?
It is a perfectly fine use case. By the way, note that you're overriding the builtin list.
To use self, you have to share a list collection between instances of a Person-class. In that case this collection should be declared as a class attribute or global list variable (not an instance attribute).
These samples of code are working:
with global list variable:
class Person:
def __init__(self, name):
self.name = name
def make_friends(self, list):
list.remove(self)
def __repr__(self):
return self.name
p1 = Person("Joe")
p2 = Person("Barack")
the_list = []
the_list.append(p1)
the_list.append(p2)
p1.make_friends(the_list)
print(the_list)
With class attribute:
class Person2:
class_list = []
def __init__(self, name):
self.name = name
Person2.class_list.append(self)
def make_friends(self):
Person2.class_list.remove(self)
def __repr__(self):
return self.name
p1 = Person2("Joe")
p2 = Person2("Barack")
print(Person2.class_list)
p1.make_friends()
print(Person2.class_list)
EDIT:
Variable 3 when a list of people is inside another class.
For accessing a list inside another class you could use attribute name or public method to get it if implemented:
class ClassWithList:
def __init__(self):
self.list_collection = []
def get_list(self):
return self.list_collection
class_with_list = ClassWithList()
class Person:
def __init__(self, name):
self.name = name
def make_friends(self, list):
list.remove(self)
def __repr__(self):
return self.name
p1 = Person("Joe")
p2 = Person("Barack")
# using implemented get-method of instance list attribute
class_with_list.get_list().append(p1)
class_with_list.get_list().append(p2)
print(class_with_list.get_list())
p1.make_friends(class_with_list.get_list())
print(class_with_list.get_list())
# instance list attribute of class`ClassWithList
print(class_with_list.list_collection)
p2.make_friends(class_with_list.list_collection)
print(class_with_list.list_collection)
Related
If a class is created with the attributes: name and list and the name attribute has a default value and the list is appending the name. Is it possible in somehow when I create an object "a" and type
"a.name = 'x' " that this 'x' will appear in the list given that the list is appending in the constructor?
class Person:
list = []
def __init__(self, name="Zed"):
self.name = name
self.list.append(name)
def printList(self):
print(self.list)
a = Person()
a.name = "Yasuo"
a.printList() #outputs Zed but Yasuo is expected.
You can make name a property, and implement a setter that updates the list.
class Person:
list = []
def __init__(self, name="Zed"):
self._name = name
self.list.append(name)
#property
def name(self):
return self._name
#name.setter
def name(self, name):
if self._name in self.list:
# remove the old name
index = self.list.index(self.name)
self.list[index] = name
else:
self.list.append(name)
self._name = name
def printList(self):
print(self.list)
a = Person()
a.name = "Yasuo"
a.printList() # prints ['Yasuo']
I am try to reference an object variable inside the class without passing it in parameters but it is throwing error
class Sample:
def __init__(self):
v = []
v.append(name)
v.append(email)
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
error:
NameError: global name 'name' is not defined
I am assigning the variable name in the object now how can i call it inside the class without adding parameters to function
if you absolutely must avoid attributes:
class Sample:
def __init__(self):
self.v = []
def addName(self, name):
self.v.append(name)
def addEmail(self, email):
self.v.append(email)
s = Sample()
s.addName("xxxx")
s.addEmail("abc#def.com")
print(s.v)
Yet another way to do this is to use decorators and #property:
class Sample(object):
def __init__(self):
self.v = [None, None]
#property
def name(self):
return self.v[0]
#property
def email(self):
return self.v[1]
#name.setter
def name(self, value):
self.v[0] = value
#email.setter
def email(self, value):
self.v[1] = value
s = Sample()
s.name = "xxxx"
s.email = "ss#ss.com"
print s.v
Notes:
Your class must be extending object explicitly in python 2 for this to work
#property decorated methods are working as "getters" and return a value
#<name>.setter is a setter method responsible for setting <name> member, so #email.setter sets the email and is being invoked when x.email = ... is called
The above may be a bit long-winded but allows for a clean API which hides the details from the user... Some people do prefer to add get/set_name methods to be more explicit but the above is more pythonic
If your requirements are dynamic, you can create attributes at run time like,
class Sample:
pass
s = Sample()
setattr(s,"name","chanda")
setattr(s,"email","xyz#gmail.com")
setattr(s,"v",[s.name,s.email])
print(s.name) #chanda
print(s.email) #xyz#gmail.com
print(s.v) #['chanda', 'xyz#gmail.com']
print(s.__dict__) #{'email': 'xyz#gmail.com', 'v': ['chanda', 'xyz#gmail.com'], 'name': 'chanda'}
I want to create a list child class that can convert all elements automatically in it to an object no matter the element is create by init or append or extend. So by using both for loop or getitem. Here's a simple example code. What kind of magic method should I use?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
c = CustomerList('a')
c.append('b')
c[0] # Object A with name a
c[1] # Object A with name b
for ele in c:
print(c)
# Object A with name a
# Object A with name b
are you asking how to override __append__?
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self,letter):
super(CustomerList, self).append(A(letter))
I guess???.. but as mentioned in the comments if you want
my_custom_list.extend(["A","B","V"])
my_custom_list[2] = "A"
to work you will need to override
def __setitem__(self,key,value): # cover a[2]='A'
super(CustomerList,self).__setitem__(key,A(value))
def extend(self,other):
super(CustomerList,self).extend([A(val) for val in other])
of coarse you probably then need to override both __add__,__iadd__ at a minimum as well
I think what you're trying to do is: When you append a new item into the list, it is an object of class A. What you can do is override list.append function:
class A():
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Object A with name {}'.format(self.name)
class CustomerList(list):
def __init__(self, *args):
super(CustomerList, self).__init__(*args)
def append(self, arg):
new_obj = A(arg)
self.insert(len(self), new_obj)
I am messing about with having a class recreate itself. I am trying to get an understanding of metaclass attribute but I am still not 100% clear.
The Goal:
A Class that creates itself for some iteration and then holds its first degree of children it created (In the example below that is one object in self.children).
class MyClass(object):
def __init__(self, num):
self.name = num
self.children = []
if num !=0:
cls = self.__new__(self.__class__ )
cls = self.__init__(num-1)
self.children.append(cls)
#Uncomment for Error
#print cls.name
if __name__ == "__main__":
c = MyClass(3)
This is what I am trying but trying to print self.name of the new object returns a kind AttributeError that "name" does not exist. I think its because I am not passing a dict of the attributes but I am looking for some clarifications of best practice and maybe a solution.
If I was not clear on something please let me know so I can better explain!
There's no need to call the __new__() or __init__() methods yourself; the constructor will handle that part automagically.
class MyClass(object):
def __init__(self, num):
self.name = num
self.children = []
if num !=0:
cls = self.__class__(num-1)
self.children.append(cls)
print cls.name
How about:
class MyClass(object):
def __init__(self, num):
self.name = num
self.children = []
if num != 0:
self.children.append(self.__class__(num - 1))
if __name__=="__main__":
c = MyClass(3)
Given that I need to operate a machine, I need a
VendingMachine class:
Property is a stock(list) that stores Food items.
Methods:
Constructor takes in no arguments.
get_stock_names(): returns a list of strings that represents the names of
all food items in the stock.
load(food): adds the Food object to stock
and others,
#predefined
class Food(object):
def __init__(self, name, nutrition, good_until):
self.name = name
self.nutrition = nutrition
self.good_until = good_until
self.age = 0
def get_name(self):
return str(self.name)
def get_age(self):
return self.age
def get_nutrition(self):
if self.age <= self.good_until:
return self.nutrition
else:
return 0
def ripen(self, days):
self.age = self.age + days
return self.age
def is_spoiled(self):
return self.good_until < self.age
#my code below
class VendingMachine:
def __init__(self):
Property = Food.get_name #no clue how to make a Property
self.load = Food.load #same here
def get_stock_names(self, Property):
lst = []
for i in Food:
i = str(i)
lst.append(i)
return lst
def has_stock(self, name):
return name in Property
def load(self, food):
Property.append(food)
return Property
def sell(self, name):
if name in Property:
Property.remove(name)
return name
else:
return None
What I get is
AttributeError: 'VendingMachine' object has no attribute 'load' (a variable)
I'm pretty sure you've misunderstood the line of your instructions telling you about the stock property. I suspect it is just telling you to make an instance variable named self.stock which holds a list of Food instances. Since the constructor takes no arguments, it presumably starts empty. Using the term "property" seems like a red herring, since property has a specific meaning in Python (a wrapper around a method to make it look like an attribute), which doesn't make much sense in this situation.
Anyway, here's what I think you want your constructor to look like:
def VendingMachine(object):
def __init__(self):
self.stock = [] # initially empty
Your later methods can inspect or manipulate self.stock as necessary.