I need to know how to check if an instance of a given class exists at runtime. So I need to make interactions between this instance and other classes. There is no relationship between these classes (composition, aggregation, and inheritance). So how do you get the reference for this class if it exists?
If you just want to know if (or how many times) a class has been instantiated, just keep a counter in the class:
class Foo:
counter = 0
def __init__(self):
Foo.counter += 1
Foo()
print(Foo.counter)
Alternatively, if you want to keep a handle on all the instances (by reference), instead store self:
class Foo:
classes = []
def __init__(self):
Foo.classes.append(self)
Foo()
print(Foo.classes[0])
Related
I have to model several cases, each case is realised by a class. I want to make sure that each class must have 2 methods get_input() and run(). So in my opinion, I can write a CaseBase class where these 2 methods are decorated as #abstractmethod. Therefore, any child class has to implement these 2 methods. And this is exactly my goal.
However, due to the nature of my work, each case is for distinct subject, and it is not easy to define a fixed group of attributes. The attributes should be defined in the __init__ method of a class. That means I don't know what exactly attributes to write in the CaseBase class. All I know is that all children cases must have some common attributes, like self._common_1 and self._common_2.
Therefore, my idea is that I also decorate the __init__ method of CaseBase class by #abstractmethod. See my code below.
from abc import ABC, abstractmethod
from typing import Dict, List
class CaseBase(ABC):
#abstractmethod
def __init__(self):
self._common_1: Dict[str, float] = {}
self._common_2: List[float] = []
...
#abstractmethod
def get_input(self, input_data: dict):
...
#abstractmethod
def run(self):
...
class CaseA(CaseBase):
def __init__(self):
self._common_1: Dict[str, float] = {}
self._common_2: List[float] = []
self._a1: int = 0
self._a2: str = ''
def get_input(self, input_data: dict):
self._common_1 = input_data['common_1']
self._common_2 = input_data['common_2']
self._a1 = input_data['a1']
self._a2 = input_data['a2']
def run(self):
print(self._common_1)
print(self._common_2)
print(self._a1)
print(self._a2)
def main():
case_a = CaseA()
case_a.get_input(input_data={'common_1': {'c1': 1.1}, 'common_2': [1.1, 2.2], 'a1': 2, 'a2': 'good'})
case_a.run()
if __name__ == '__main__':
main()
My question: Is my way a good Python style?
I followed many Python tutorials about how to make Abstract class and child class. They all give examples where a fixed group of attributes are defined in the __init__ method of the base class. I also see some approach to use super().__init__ code in the child class to change the attributes defined in the base class or to add new attributes. But I am not sure if it is better (more pro) than my way.
Thanks.
You mostly used the abc module in python 3.10 correctly. but it doesn't make sense to decorate the constructor with #abstractmethod. It's unnecessary. Each class, derived or not, can and will have its own constructor. You can call super().__init__(args) within the child class to call the constructor of its immediate parent if you didn't want to duplicate its code but wanted to do further initialization in the child class constructor.
I know that self keyword in python is a reference to the instance of that particular class, but how can one create an object within the same class? can someone please explain this concept to me in detail?
I think first of all that you should be aware of the differences between class, object and instance.
The class is basically the code definition of an entity.
An object or instance, usually mean the same exact thing: a running unique specific entity loaded in memory.
I personally make a distinction between the two, but this is probably just my opinion:
I use object in a phase when I am reading the code functionally and I want to say something like this is the object kind returned by this method.
I use instance when referring to the actual object running in memory.
===
Now in a python class, any member can be defined as an object, for example:
class MyClass(object):
def __init__(self):
self.some_member = MyOtherClass()
Please note that the class itself inherit from object, which is the base class (or the mother of all the python classes).
In [1]: object??
Init signature: object()
Docstring:
The base class of the class hierarchy.
When called, it accepts no arguments and returns a new featureless
instance that has no instance attributes and cannot be given any.
Type: type
Subclasses: type, weakref, weakcallableproxy, weakproxy, int, bytearray, bytes, list, NoneType, NotImplementedType, ...
===
If you meant instead, "How can I add an instance of the same class as a member of the class?", the following could be a way to do it:
class MyClass(object):
def __init__(self):
self.another_instance = None
def set_instance(self, instance):
if not isinstance(instance, MyClass):
raise TypeError("Wrong instance type!")
self.another_instance = instance
a = MyClass()
b = MyClass()
a.set_instance(b)
Here I will also share with you the wrong approach:
class MyClass(object):
def __init__(self):
self.another_instance = MyClass()
a = MyClass()
This code will result in a RecursionError: maximum recursion depth exceeded. This because if you think about it, each class instance will try to create a new instance, which will try to create a new instance, which will try... and so on.
====
This could be another way to do it, but I wouldn't suggest it unless for a very specific and particular case (maybe something related to chained objects, but there's surely a better way to manage this.)
In [1]: class MyClass(object):
...: def __init__(self, has_link=False):
...: if has_link:
...: self.another_instance = MyClass(has_link=False)
...:
In [2]: a = MyClass(has_link=True)
In [3]: a.another_instance
Out[3]: <__main__.MyClass at 0x110fe00d0>
Is it possible to access a class object or its inner class object from a class static variable in python3?
class OuterClass:
all_subclasses = {
# is it possible to access the OuterClass from a class static variable
'innerclass1': OuterClass.InnerClass1
}
#classmethod
isInnerClass(cls, identifier: str):
return identifier.lower() in cls.all_subclasses
class InnerClass1:
def __init__(self):
pass
If not, what will be alternative for this?
You can refer to attributes of the class directly in the class definition, as long as the reference comes after the definition:
class A:
class B:
pass
x = B
print(A.x)
# <class '__main__.A.B'>
This has some caveats. For reasons that are very complicated, you can't use class attributes directly in a comprehension in the class definition:
class A:
class B:
pass
x = [B for _ in range(5)] # NameError: name 'B' is not defined
You also can't refer to the class itself in it's own definition:
class A:
x = A # NameError: name 'A' is not defined
This is because class definition is basically another way of creating a type object
class A:
x = 1
A = type('A', (object,), {'x': 1})
And it makes total sense both that you can't use an object before it's created and that you can't refer to it by a name it hasn't been assigned to yet.
It's important to note that this all applies only to the class definition itself, that is to say all of the code that gets executed directly as the class is created. Code that gets executed later, like method definitions, can refer to the class like any other code or through type(self)
I'm wondering if I have:
class A(object):
def __init__(self):
self.attribute = 1
self._member = 2
def _get_member(self):
return self._member
def _set_member(self, member):
self._member = member
member = property(_get_member, _set_member)
class B(object):
def __init__(self):
self._member = A()
def _get_a_member(self):
return self._member.member
def _set_a_member(self, member):
self._member.member = member
member = property(_get_a_member, _set_a_member)
Can I somehow avoid to write get/setters for A.member, and simply refer to the attribute or property of the A object?
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute, then writing get/setters seems like overhead.
I think even if I could write the get/setters inline that would help?
I find the question a bit unclear, however I try to explain some context.
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute
If there is no logic in getter/setters, then there is no need to define the attribute as a property, but the attribute can be used directly (in any context).
So
class A(object):
def __init__(self):
self.attribute = 1
self.member = 2
class B(object):
def __init__(self):
self.member = A()
B().member.member # returns 2
B().member.member = 10
In some languages, it's considered good practice to abstract instance properties with getter/setter methods, That's not necessarily the case in Python.
Python properties are useful when you'd need more control over the attribute, for example:
when there is logic (validation, etc.)
to define a readonly attribute (so only providing a getter without a setter)
Update (after the comment)
properties are not necessarily a tool to "hide" some internal implementation. Hiding in Python is a bit different than say in Java, due to very dynamic nature of Python language. It's always possible to introspect and even change objects on the fly, you can add new attributes (even methods) to objects on runtime:
b = B()
b.foo = 4 # define a new attribute on runtime
b.foo # returns 4
So Python developers rely more on conventions to hint their intentions of abstractions.
About the polymorphic members, I think it's most natural for Python classes to just share an interface, that's what's meant by Duck typing. So as long as your next implementation of A supports the same interface (provides the same methods for callers), it should not be any issue to change its implementation.
So this is what I came up with - use a method to generate the properties, with the assumption that the obj has an attribute of _member:
def generate_cls_a_property(name):
"""Small helper method for generating a 'dumb' property for the A object"""
def getter(obj):
return getattr(obj._member, name)
def setter(obj, new_value):
setattr(obj._member, name, new_value)
return property(getter, setter)
This allows me to add properties like so:
class B(object):
def __init__(self):
self._member = A()
member = generate_cls_a_property('member') # generates a dumb/pass-through property
I'll accept my own, unless someone tops it within a week.. :)
This question already has answers here:
Counting instances of a class?
(7 answers)
How to count the number of instance of a custom class?
(1 answer)
Closed 4 years ago.
I have made an abstract base class using metaclass=ABCMeta to implement some default methods and properties that all its derived classes should have, something like this:
class BaseClass(metaclass=ABCMeta):
def __init__(self):
self.params = OrderedDict()
# some function all children must implement
#abstractmethod
def fn():
pass
# some property all children will have
#property
def n_params(self):
return len(self.params)
Now, I want to count how many instances of each derived class are created, because I want to print their name with a number. I can easily implement it like this:
class ChildClass(BaseClass):
# nr of instances of ChildClass
_n = 0
def __init__(self, mu, sigma, amp):
# initialize ABC
super().__init__()
ChildClass._n += 1
self.name = f'ChildClass {ChildClass._n}'
# must be overridden by each child class
#staticmethod
def fn(name):
# do stuff
print(f'hello {name}')
However, I need to implement this in each class that derives from BaseClass separately. It would be much more elegant to implement it in BaseClass itself.
I am looking for something that works like the opposite of super(), maybe something like this:
class BaseClass(metaclass=ABCMeta):
# instance counter for derived classes
child()._n = 0
def __init__(self):
self.params = OrderedDict()
child()._n += 1
Can I implement a class level variable ChildClass._n in BaseClass? And if so, how can I access that variable in BaseClass.__init__?
Edit:
To clarify: I already have a base class, from which I derive many other child classes. The fact that all these classes share many properties is one of the main reasons I decided to use a base class in the first place. It thus seems superfluous to need to implement something as simple as an instance counter separately in each derived class.
Accessing a child class variable seems to be already adressed here. The question that remains is, how do I define a class level variable in my abstract base class, that is different for each child class.