Python, delete a list item from class method - python

I have my class.
I want to create a method inside to delete a list item by code attribute.
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
print("The code: {self.__code} was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
print(list)
lista.deleteitem(123)
How I can create a method who deletes the code that I send?
Regards

You can try this below :
class MyClass(Base):
def __init__(self, code, name):
self.__code = code
self.__name = name
#property
def code(self):
return self.__code
#property
def name(self):
return self.__name
#code.setter
def code(self, new_code):
self.__code=new_code
def __repr__(self):
x = f"Code: {self.__code} and Name:{self.__name}"
return(x)
def __deleteitem__(self, code):
# Logic for deletion
for obj in list:
if obj.code == code:
list.remove(obj)
print("The code: "+code+" was deleted")
list=[]
list.append(MyClass(1234,"Aijio"))
list.append(MyClass(123,"Anodnd"))
list.append(MyClass(1236,"Jfifi"))
list.append(MyClass(1238,"Roberto"))
myclass = MyClass(None, None)
myclass.__deleteitem__(123)

Related

Achieving single-responsibility principle with python abstract classes

I want to separate the DB models from the actual classes. But i need two static functions for fetching data from the DB regardless of the subclass type. the implementation for both functions are the same across all DB models.
pyright showing an error that cls inside get() and get_all() functions doesn't have a db property.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name):
self.name = name
#abstractstaticmethod
def save(m):
pass
#abstractstaticmethod
def _from_model(obj):
pass
#classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
#classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class DogSound:
def __init__(self, name):
self.name = name
def sound(self):
print(self.name, ": DOG SOUND!!")
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super(Dog, self).__init__(name)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
Dog.get(1).sound()
I cannot duplicate your first error.
Your second issue is a result of method sound implicitly returning None since it has no return statement and you have print(Dog.get(1).sound()), which will print out the return value from that method. You either want to change this to just Dog.get(1).sound() or modify the sound method to return what it is currently being printed and remove the print statement (my choice).
As an aside, I found this class structure a bit difficult to follow. Why do you need a separate DogSound class with a name attribute which should belong to Animal? Also, it seems to me that age could/should be an attribute of Animal since both cats and dogs have an age.
from abc import ABC, abstractstaticmethod
class DogsDB:
lists = ["DOG1", "DOG2", "DOG3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class CatsDB:
lists = ["CAT1", "CAT2", "CAT3"]
#classmethod
def get(cls, id):
return cls.lists[id]
class Animal(ABC):
def __init__(self, name, age):
self.name = name
self.age = age
#abstractstaticmethod
def save(m):
pass
#abstractstaticmethod
def _from_model(obj):
pass
#classmethod
def get(cls, id):
obj = cls.db.get(id)
return cls._from_model(obj)
#classmethod
def get_all(cls):
objs = cls.db.lists
lists = []
for obj in objs:
e = cls._from_model(obj)
lists.append(e)
return lists
def __repr__(self):
return self.name
class Dog(Animal):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
def sound(self):
return f"{self.name}: DOG SOUND!!"
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
class Cat(Animal):
db = CatsDB
def __init__(self, name, age):
super().__init__(name, age)
self.age = age
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Cat(obj, 4)
print(Cat.get(1))
print(Dog.get(1))
print(Cat.get_all())
print(Dog.get_all())
print(Dog.get(1).sound())
Prints:
CAT2
DOG2
[CAT1, CAT2, CAT3]
[DOG1, DOG2, DOG3]
DOG2: DOG SOUND!!
If for some reason you want DogSound to be a separate class, then there is no need for the name attribute to be duplicated:
...
class DogSound: # A "Mixin" class
def sound(self):
return f"{self.name}: DOG SOUND!!"
class Dog(Animal, DogSound):
db = DogsDB
def __init__(self, name, age):
super().__init__(name, age)
#staticmethod
def save(m):
print(m)
#staticmethod
def _from_model(obj):
return Dog(obj, 4)
...

How '#decorator" actually works in python?

How '#decorator' actually works?
I just knew it works like this:
def deco(func):...
#deco
def func():...
# same
def func():...
func = deco(func)
But it doesn't work well in '#class.method'
Below is an example:
class Person:
def __init__(self, name):
self._name = name
#property
def name(self):
return self._name
#name.setter
def name(self.value):
self._name = value
class Person:
def __init__(self, name):
self._name = name
## #propery
def name(self):
return self._name
name = property(name)
## #name.setter
def name(self, value):
self._name = value
name = name.setter(name) <----- error
The error here is because name has been changed to point to "def name(self.value):..."
I'd like to know how '#property.method' actually works.
I just guessed like that:
class Person:
def __init__(self, name):
self._name = name
## #propery
def name(self):
return self._name
name = property(name)
## #name.setter
x = name.setter
def name(self, value):
self._name = value
name = x.setter(name)
del x
Is it right or is there other way to work that I don't know?
Thank you for reading!

How to convert all elements automatically in a list to a given object in Python

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)

Notify parent instance about property change

I have these two classes:
class Status(object):
def __init__(self):
self._message = ''
#property
def message(self):
return self._message
#message.setter
def message(self, value):
self._message = value
class Buddy(object):
def __init__(self, name):
self.name = name
self.status = Status()
def status_updated(self):
# this should be called when self.status.message is changed
and I use them like this:
buddy = Buddy('John')
buddy.status.message = 'Hello world!' # this should call Buddy.status_updated
I want Buddy.status_updated to be called when I modify the message property of Status. How to achieve this?
You'll have to store a reference back to the parent; python values do not track where they are stored (there can be multiple places that refer to your Status() instances):
class Status(object):
def __init__(self, parent=None):
self._message = ''
self._parent = parent
#property
def message(self):
return self._message
#message.setter
def message(self, value):
self._message = value
if self._parent is not None:
self._parent.status_updated()
class Buddy(object):
def __init__(self, name):
self.name = name
self.status = Status(self)
def status_updated(self):
# this should be called when self.status.message is changed
In each case you need somehow to register you want to "listen" to other's object property changes. I would suggest simple solution like this:
class Status(object):
def __init__(self, on_message_change=None):
self._message, self._on_message_change = '', on_message_change
#property
def message(self):
return self._message
#message.setter
def message(self, value):
if self._on_message_change:
self._on_message_change(self._message, value)
self._message = value
class Buddy(object):
def __init__(self, name):
self.name = name
self.status = Status(self.status_updated)
def status_updated(self, old_value, new_value):
print("status changed '%s' -> '%s'" % (old_value, new_value))
b = Buddy("someone")
b.status.message = "init"
b.status.message = "new"
output is:
status changed '' -> 'init'
status changed 'init' -> 'new'

Python static dictionary in class that supports item assignment

I have a class that contains a static dictionary:
class MyClass:
my_dict = {}
def __init__(self, name):
self.name = name
MyClass.my_dict[self.name] = []
def __call__(self, data):
MyClass.my_dict[self.name].append(data)
Whenever I want to update the dictionary, I have to use MyClass.my_dict[key], but I'd like the class itself to support item assignment so I can just use MyClass[key] to do the same thing. Is there a way to do this? I'm using Python 2.7.
So, here's what I ended up doing:
class MyClassType(type):
my_dict = {}
def __getitem__(cls, key):
return cls.my_dict[key]
def __setitem__(cls, key, value):
cls.my_dict[key] = value
def __str__(cls):
return cls.my_dict.__str__()
def iteritems(cls):
return cls.my_dict.iteritems()
class MyClass(object):
__metaclass__ = MyClassType
def __init__(self, name):
self.name = name
MyClass[self.name] = []
def __call__(self, data):
MyClass[self.name].append(data)

Categories