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)
Related
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)
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 was reading source code of a banking application and the class bank is defined below:
class Bank(object):
""" the bank class contains all the bank operations """
def __init__(self, name):
""" instantiate the class """
self.name = str(name)
self.customers = Customers()
Now self.customers is another instance of Customers class which is defined below:
class Customers(dict):
""" the customers class extends the dictionary object """
def __setitem__(self, key, item):
self.__dict__[key] = item
def __getitem__(self, key):
return self.__dict__[key]
def __repr__(self):
return repr(self.__dict__)
def __len__(self):
return len(self.__dict__)
def __delitem__(self, key):
del self.__dict__[key]
def keys(self):
return self.__dict__.keys()
def values(self):
return self.__dict__.values()
def __cmp__(self, dict):
return cmp(self.__dict__, dict)
def __contains__(self, item):
return item in self.__dict__
def add(self, key, value):
self.__dict__[key] = value
def __iter__(self):
return iter(self.__dict__)
def __call__(self):
return self.__dict__
def __unicode__(self):
return unicode(repr(self.__dict__))
As per my understanding we override a function when a new functionality is added or its behaviour is changed from previous function. Why we are overriding the functions of dict in Customer class. Can't we simply just use self.customers = dict() ? Since we are not adding anything new here.
The class is more than just a dict; it supports attribute access for the keys too, because it delegates all dictionary access to the instance __dict__ attribute, which contains all attributes.
Demo:
>>> c = Customers()
>>> c.foo = 'bar'
>>> c
{'foo': 'bar'}
>>> c['foo']
'bar'
You can't do that with a regular dictionary. The implementation you found is a rather elaborate version of the answers to this question: Accessing dict keys like an attribute in Python?
I want a python class that is composed partly of specific methods from other classes which operates on self in the "composed class". How do I do that?
E.g. if I want to include specific methods from classA and classB in my new class "theClass":
# Some classes to "inherit" from
class classA(object):
def methA1(self, value):
self.attrib = value*1
def methA2(self, value):
self.attrib = value*2
class classB(object):
def methB1(self, value):
self.attrib = value*3
def methB2(self, value):
self.attrib = value*4
# The class I want to build
class theClass(object):
# WHAT TO DO HERE?
# -------------------
methA1 = classA.methA1
methB2 = classB.methB2
# -------------------
# /WHAT TO DO HERE
# add additional methods...
def methC(self, value):
self.attrib = value*5
# I want the following behavior
instance = theClass()
instance.methB2(5) # sets instance.attrib to 20
instance.methA2(5) # error, does not exist
You could use mixins:
class MixinA1(object):
def methA1(self, value):
self.attrib = value*1
class MixinB2(object):
def methB2(self, value):
self.attrib = value*4
class classA(MixinA1):
def methA2(self, value):
self.attrib = value*2
class classB(MixinB2):
def methB1(self, value):
self.attrib = value*3
# The class I want to build
class theClass(MixinA1, MixinB2):
def methC(self, value):
self.attrib = value*5
Mixins make sense if the Mixin class encapsulates some unit of functionality which you desire to add on to multiple classes.
If the methods don't naturally break down into units of functionality,
here is another alternative:
def methA1(self, value):
self.attrib = value*1
def methA2(self, value):
self.attrib = value*2
def methB2(self, value):
self.attrib = value*4
def methB1(self, value):
self.attrib = value*3
def methC(self, value):
self.attrib = value*5
class classA(object):
methA1 = methA1
methA2 = methA2
class classB(object):
methB1 = methB1
methB2 = methB2
class theClass(object):
methA1 = methA1
methB2 = methB2
methC = methC
This is very similar to the alternative you've already posted, except that it places except that it places all classes on an equal footing -- initially the methods are not associated with any particular class. This might be preferable so theClass is not "breaking encapsulation" by reaching in and nabbing a method from a class (such as classA) on which it does not explicitly depend.
I have some classes:
class Window(object):
def __init__(self, name):
self.wind_name = name
def getWindowName(self):
return 'wnd' + self.wind_name
class Control(object):
def __init__(self, name, wnd):
self.contrl_name = name
setattr(self, 'getWindowName', wnd.getWindowName)
setattr(self, 'wind_name', wnd.wind_name)
def getControlName(self):
return (self.getWindowName(), 'unk' + self.contrl_name)
class Button(Control):
def __init__(self, name, wnd):
super(Button, self).__init__(name, wnd)
def getControlName(self):
return (self.getWindowName(), 'btn' + self.contrl_name)
wnd = Window('MyApp')
btnOK = Button('OK', wnd)
btnOK.getControlName() # work ok., return ('wndMyApp', 'btnOK')
btnOK.wind_name = 'NewApp'
btnOK.getControlName() # does not work properly., return ('wndMyApp', 'btnOK')
How can I extend the class Control|Button from the object of class Window to access the functions getWindowName and field wind_name in objects btnOK?
Is there a way without creating a field self.wnd = wnd in class Control, or add method setWindowName in Window...?
I can not inherit class Control from the class Window! This is not logical.
Python allows inheriting from multiple classes, i.e.
class Button(Control, Window):
...
But in this case you should know exactly what you are doing (speaking of Pythons Method Resolution Order (MRO)). I'd recommend reading this small book: Python Attributes and Methods.
You can use property for attributes
class Window(object):
def __init__(self, name):
self.wind_name = name
def getWindowName(self):
return 'wnd' + self.wind_name
class Control(object):
def __init__(self, name, wnd):
self.contrl_name = name
self.wnd = wnd
setattr(self, 'getWindowName', wnd.getWindowName)
def get_wind_name(self):
return self.wnd.wind_name
def set_wind_name(self, v):
self.wnd.wind_name = v
wind_name = property(get_wind_name, set_wind_name)
def getControlName(self):
return (self.getWindowName(), 'unk' + self.contrl_name)
class Button(Control):
def __init__(self, name, wnd):
super(Button, self).__init__(name, wnd)
def getControlName(self):
return (self.getWindowName(), 'btn' + self.contrl_name)
wnd = Window('MyApp')
btnOK = Button('OK', wnd)
print btnOK.getControlName() # work ok., return ('wndMyApp', 'btnOK')
btnOK.wind_name = 'NewApp'
print btnOK.getControlName()