Define methods for multiple classes - python

I'm working on a small personal project where I created many classes. Each class has its own register containing all its instances:
class IterReg(type):
# Register of all objects for iteration
def __iter__(cls):
return iter(cls._reg.values())
The "template" which I use for each class is
class Point(object):
# Point object
__metaclass__ = IterReg
_reg = dict()
counter = 0
# Initialize
def __init__(self, name):
self.name = name
self._reg[self.name] = self
Point.counter += 1
# Return register keys
#staticmethod
def get_reg_keys(cls):
return cls._reg.keys()
And some other (not important for a MWE) stuff.
If I initialize, e.g., a = Point("Point A"), I can then call:
>>> a.get_reg_keys()
['Point A']
which is (obviously) the same result that I get from
Point.get_reg_keys()
Now my question: is there a way to define this method once for all classes (i.e. somehow in the metaclass).
I first thought something like this had worked:
class IterReg(type):
# Register of all objects for iteration
def __iter__(cls):
return iter(cls._reg.values())
def get_reg_keys(cls):
return cls._reg.keys()
But then I can just call get_reg_keys() from the class (i.e. Point.get_reg_keys()) and not from any instance of it.

You can define a generic class that has .get_reg_keys() and subclass it when you want to use that method. In the below example, any class that inherits from Generic will have the .get_reg_keys() method.
class IterReg(type):
# Register of all objects for iteration
def __iter__(cls):
return iter(cls._reg.values())
class Generic(object):
#classmethod
def get_reg_keys(cls):
return cls._reg.keys()
class Point(Generic):
# Point object
__metaclass__ = IterReg
_reg = dict()
counter = 0
# Initialize
def __init__(self, name):
self.name = name
self._reg[self.name] = self
Point.counter += 1
a = Point('Point A')
a.get_reg_keys()
# returns:
['Point A']

Related

Anyone knows how to create an attribute of a Class which will be a '''set''' of all instances of that class?

I know that each instance will inherit that attribute, but I want a function or should I call it a method of that class to return the set of all instances created of that class.
So let's say I created 3 instances and call a method from the last one that will return all the previously created instances as well as the one that I am calling it from.
I was able to achieve it by making a list, but would it be possible to return a set?
Is there some kind of constructor that I am missing for it?
class Bee():
instances = []
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
def __str__(self):
self.instances.append(f"{self.identifier} {self.name}")
return f"{self.identifier} {self.name}"
def get_hive(self):
return self.instances
Normally you would create Hive as a separate class and put the Bees inside. You then have a clear and explicit data structure whose job includes keeping track of all Bees created.
Something like:
class Hive:
def __init__(self):
self.bees = []
def add_bee(self, bee):
self.bees.append(bee)
class Bee:
def __init__(self, name, identifier):
self.name = name
self.identifier = identifier
def __str__(self):
return f"Bee({self.name}, {self.identifier})"
def __repr__(self):
return str(self)
# User code example
hive = Hive()
b1 = Bee('My Bee', 0)
b2 = Bee('Some Other Bee', 1)
hive.add_bee(b1)
hive.add_bee(b2)
print(hive.bees) # display all bees inside the hive

Create child class object using parent class instance

lets say we have class A and it has one instance - x. How to make a child class of class A where I would be able to pass x as an argument and get all its parameters and pass it to child class object. precisely speaking I want to do something like this.
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
super().__init__(**Ainstance.__dict__)
self.someParameter = someParameter
x = A(parameter1='1', parameter2='2')
x = B(x, someParameter='3')
print(x.parameter1)
print(x.parameter2)
print(x.someParameter)
the goal is to create a class where I would be able to get all the parameters of parent class object, and add my own attributes. The problem in the code above is I won't be able to do that with all classes because not all of them has __dict__ attribute.
I have this example code which I use to remind myself how to construct a proxy.
#soProxyPattern
class Example:
def __init__(self):
self.tag_name = 'name'
def foo(self):
return 'foo'
def bar(self, param):
return param
class Container:
def __init__(self, contained):
self.contained = contained
self.user_name = 'username'
def zoo(self):
return 0
def __getattr__(self, item):
if hasattr(self.contained, item):
return getattr(self.contained,item)
#raise item
c = Container(Example())
print(c.zoo())
print(c.foo())
print(c.bar('BAR'))
print(c.tag_name)
print(c.user_name)
The output is:
0
foo
BAR
name
username
This shows that Container can have its own attributes (methods or variables) which you can access over and above all of the attributes of the contained instance.
Instead of dict you could use the dir and getattr like this:
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
parameters = {param: getattr(Ainstance, param) for param in dir(Ainstance) if not param.startswith("__")}
super().__init__(**parameters)
self.someParameter = someParameter
For a more detailed explanation see: Get all object attributes in Python?

Access attribute of one instance from another instance defined in that instance

Sorry for the confusing question.
Say there are two instances of two different classes (e.g. 'big_instance' and 'little_instance').
The little_instance is defined as an attribute of the big instance.
How would a method in the little class access an attribute of the big instance.
An example is below.
The line 'return parent.attribute1' is basically pseudo code. How would this line be written properly?
class BigClass:
def __init__(self, att):
self.attribute1 = att
self.little_instance = LittleClass()
class LittleClass:
def parents_att(self):
return parent.attribute1
big_instance = BigClass(1)
print(big_instance.little_instance.parents_att())
ah yes I got it. Read the comments for explanation.
The test code at the end shows that it works even after attribute1 changes :)
class BigClass:
def __init__(self, att):
self.attribute1 = att
# pass in self
self.little_instance = LittleClass(self)
class LittleClass:
def __init__(self, the_big_class):
# the big class is held in an instance var
self.the_big_class = the_big_class
def parents_att(self):
# the instance var is used to reference the attribute
return self.the_big_class.attribute1
big_instance = BigClass(1)
print(big_instance.little_instance.parents_att())
big_instance.attribute1 = 2
print(big_instance.little_instance.parents_att())
You can do the following if you want to access attribute from BigClass into LittleClass.
class BigClass:
def __init__(self, att):
self.attribute1 = att
class LittleClass(BigClass):
def __init__(self, att):
BigClass.__init__(self, att)
def parent_att(self):
return self.attribute1
small_instance = LittleClass(1)
print(small_instance.parent_att)

Access Child class variables in Parent class

I have a Parent class and a inherited child class, I would like to know how to access the child class variable in my Parent class..
I tried this and it fails -
class Parent(object):
def __init__(self):
print x
class Child(Parent):
x = 1;
x = Child();
Error:-
NameError: global name 'x' is not defined
This question is in relation to Django forms where we inherit the form class
and declare some class variables.
For example:-
My form looks like this
from django import forms
class EmployeeForm(forms.Form):
fname = forms.CharField(max_length=100)
lname = forms.CharField(max_length=100)
I believe the form fields are considered as class variable and somehow passed to the parent class..
Django does this with metaclasses. (Relevant Django source)
Here's a distilled example of the relevant code:
class Field(object):
def __init__(self, *args):
self.args = args
def __repr__(self):
return "Form(%s)" % (', '.join(map(repr, self.args)),)
class Meta(type):
def __new__(mcs, name, bases, attrs):
field_list = []
for k,v in attrs.items():
if isinstance(v, Field):
field_list.append(v)
cls = type.__new__(mcs, name, bases, attrs)
cls.fields = field_list
return cls
class Form(object):
__metaclass__ = Meta
class MyForm(Form):
fe1 = Field("Field1", "Vars1")
fe2 = Field("Field2", "Vars2")
x = "This won't appear"
form_fields = MyForm.fields
print(form_fields)
There are many questions on here about Python metaclasses (example), so I won't try to re-explain the concept.
In this case, when you create the class MyForm, each of the class attributes are checked for being instances of Field. If they are, they're added to a list (field_list).
The class is created, then an attribute .fields is added to the class, which is field_list, the list of Field elements.
You can then access the form fields through <FormSubclass>.fields or in the case of this example, MyForm.fields.
Edit:
It's worth noting that you can accomplish very similar functionality, without the metaclass syntactic sugar with something like:
class Field(object):
def __init__(self, *args):
self.args = args
def __repr__(self):
return "Form(%s)" % (', '.join(map(repr, self.args)),)
class Form(object):
def __init__(self):
self._fields = None
def fields(self):
if self._fields is None:
field_list = []
for k in dir(self):
v = getattr(self, k)
if isinstance(v, Field):
field_list.append(v)
self._fields = field_list
return self._fields
class MyForm(Form):
def __init__(self):
Form.__init__(self)
self.fe1 = Field("Field1", "Vars1")
self.fe2 = Field("Field2", "Vars2")
self.x = "This won't appear"
form_fields = MyForm().fields()
print(form_fields) # [Form('Field1', 'Vars1'), Form('Field2', 'Vars2')]
Short answer : you dont access subclasse's attributes from a parent class - because the parent class can not know what attributes a child class might have.
Long answer : ... unless the parent class defines a protocol allowing subclasses to let the parent class knows about at least part of it's own attributes.
Django's form framework (as well as django's orm FWIW) use such a protocol: the base Form class has a custom metaclass that collects the form.fields declared in a subclass - and do quite some black magic. FWIW, Django is oss so you could have answered the question yourself just reading the source code: https://github.com/django/django/blob/master/django/forms/forms.py
You need to refer to self.x to access Child class variables:
class Parent(object):
def __init__(self):
print(self.x)
class Child(Parent):
x = 1
if __name__ == '__main__':
child_instance = Child()
This might not help you in regards to Django Forms, but another alternative is to work with abstract classes. You would exchange attributes with methods/properties. It also prevents you from using the parent class by itself.
from abc import ABC, abstractmethod
class Parent(ABC):
#property
#abstractmethod
def x(self):
pass
def __init__(self):
print(self.x)
class Child(Parent):
#property
def x(self):
return 1
if __name__ == '__main__':
child_instance = Child() # prints "1"
parent_instance = Parent() # fails
Well, if I got you right... Maybe you're thinking of getting a field from the child class to work on the parent class. Well, that's polymorphism and it's done by overriding the parent class.
Let's assume you have :
A parent has x, now to increase x from the child and make it reflect in the parent, check the code below to get it.
class Parent:
def __init__(self, x):
self.x = x
def Print(self):
print(f"{self.x}")
class Child(Parent):
def __init__(self, x):
Parent.__init__(self, x)
x += 1
self.x = x
""""""
c1 = Child(2)
c1.Print()
#output: 3
""""""
c2 = Child(8)
c2.Print()
#output: 9

Instance of a modified dict class should return one of the values

I wonder if it is possible to create a Python class with following properties:
It should have all properties of the list or dict, i.e. inherited from one of them
When the instance is called it would return an element predefined by index or key
For example:
class A(dict):
def __init__(self, name):
self.name = name
self['a'] = 1
self['b'] = 2
a = A('a')
and when instance a is called it would return 1 as defined by the key 'a'. The original access through the keys should still be available.
The problem X:
I have a class Fruits that is inherited from dict. In self it can have several instances of class Fruit, however often there is only one instance. So when I am working with instance of Fruits I want to use methods and attributes of the that single instance as if they were attributes and methods of A:
class Fruit(object):
def __init__(self):
self.name = 'apple'
class Fruits(dict):
def __init__(self, name):
self.fruit_name = name
self['apple'] = Fruit()
a = Fruits('apple')
I want a.name to return 'apple'. I have the solution using #property:
class Fruits(dict):
def __init__(self, name):
self.fruit_name = name
self['apple'] = Fruit()
#property
def name(self):
return self[self.fruit_name].name
but I am looking for something better...
Not sure if I've followed your question completely, but you can't call an instance directly; you can call a function within the instance. Now, since a is an instance of dict, you can access its keys -
In [9]: a['a']
Out[9]: 1
Or,
In [10]: a[a.name]
Out[10]: 1
You can implement the __call__ method within A
class A(dict):
def __init__(self, name):
self.name = name
self['a'] = 1
self['b'] = 2
def __call__(self):
return self[self.name]
Then,
In [24]: a = A('a')
In [25]: a()
Out[25]: 1
Is this along the lines of what you're looking for?

Categories

Resources