How does python3 diamond inheritance works for data fields? How to initialize the inherited fields with super()._init__? - python

I was checking this problem to understand multiple inheritance and I got stuck.
How can I set the fields of the inherited objects from the last class?
class Vehicle():
def __init__(self, name:str, seats:int):
self.name = name
self.seats = seats
def print_vehicle(self):
print(f'Vehicle {self.name} has {self.seats} seats')
class Boat(Vehicle):
def __init__(self, name:str, seats:int, engine_type:str):
super().__init__(name, seats)
self.engine_type = engine_type
def print_vehicle(self):
print(f'Boat {self.name} has {self.seats} seats and engine {self.engine_type}')
class Car(Vehicle):
def __init__(self, name:str, seats:int, fuel:str):
super().__init__(name, seats)
self.fuel = fuel
def print_vehicle(self):
print(f'Car {self.name} has fuel {self.fuel}')
class AnphibiousCar(Boat, Car):
def __init__(self, name, seats, engine_type, fuel):
super(AnphibiousCar, self).__init__(name, seats, engine_type) # ???
def print_vehicle(self):
print(f'Anphibious car {self.name} has {self.seats} seats and {self.engine_type} - {self.fuel} engine')
ac = AnphibiousCar('name', 4, 'piston', 'gas')
ac.print_vehicle()

The point is that each class should focus only on the stuff which is its direct responsibility; the rest should be delegated to superclasses (and note that, when you deal with such a cooperative inheritance with super(), your methods that call super() should not need to know what exactly are the actual superclasses, in particular the nearest one - as this can change, depending on the actual class of self).
So let's reimplement your classes (with a bunch of explanations in the comments):
class Vehicle:
# Added the `*,` marker to make `name` and `seats` *keyword-only*
# arguments (i.e., arguments that are identified only by their
# *names*, never by their positions in a call's arguments list).
def __init__(self, *, name: str, seats: int):
self.name = name
self.seats = seats
# We abstract out class-specific features into separate methods,
# keeping in the `print_vehicle()` method only the common stuff,
# so that in subclasses we'll need to customize only those methods
# (`list_features()`, `get_type_label()`), *not* `print_vehicle()`.
def print_vehicle(self):
vehicle_type_label = self.get_type_label()
features = ', '.join(self.list_features())
print(f'{vehicle_type_label} {self.name}: {features}.')
# Side note: the `list[str]` type annotation requires Python 3.9
# or newer (for compatibility with older versions you need to
# replace it with `List[str]`, using `from typing import List`).
def list_features(self) -> list[str]:
return [f'has {self.seats} seats']
# This implementation is, in fact, quite generic (so that
# in most subclasses we will *not* need to customize it).
def get_type_label(self) -> str:
return self.__class__.__name__
class Boat(Vehicle):
# Only `Boat`-specific arguments (as keyword-only ones, as above...)
# are declared here explicitly. Any other are treated as a "black
# box", just being passed into superclasses...
def __init__(self, *, engine_type: str, **kwargs):
super().__init__(**kwargs)
self.engine_type = engine_type
# Also here we focus only on this-class-specific stuff, handling
# other stuff as "agnostically" as possible...
def list_features(self) -> list[str]:
return super().list_features() + [f'has {self.engine_type} engine']
class Car(Vehicle):
# And analogously...
def __init__(self, *, fuel: str, **kwargs):
super().__init__(**kwargs)
self.fuel = fuel
def list_features(self) -> list[str]:
return super().list_features() + [f'needs {self.fuel} fuel']
class AmphibiousCar(Boat, Car):
# Note: here we get our `__init__()` and `list_features()`
# for free (!), as the superclasses provide all we need
# when it comes to those two methods.
# The only thing we may want to customize is:
def get_type_label(self) -> str:
return 'Amphibious car'
ac = AmphibiousCar(
name='Julia-III',
seats=4,
engine_type='piston',
fuel='gas')
# "Amphibious car Julia-III: has 4 seats, needs gas fuel, has piston engine."
ac.print_vehicle()
As a further reading, I'd recommend: https://rhettinger.wordpress.com/2011/05/26/super-considered-super/

You have some errors:
super(AnphibiousCar, self).__init__(name, seats, engine_type) could become
Boat.__init__(self, name, seats, engine_type) so calling the class you could
give information about how to initialize it.
there is a missing parameter in Boat where you should give a fuel argument
to the superclass Vehicle, like super().__init__(name, seats, "oil")
As you can note if you use super you don't need to pass self, if you use
the class name you are using it.
My point of view is that, yes, is good to understand, but don't loose to much
time as this kind of multiple inheritance is only theoretical and practically
not used in real coding. This in fact can cause a lot of confusion and add
boilerplate... "new" languages like, for example, Rust do not even provide
inheritance.
Just to say: "Yes, study it, but keep it simple" ^_^

Related

Using metaclasses instead of factory pattern

Lets suppose we have an entity (Car) with different CarTypes:
class CarTypes(Enum):
SUV = 'suv'
SPORT = 'sport'
#dataclass
class Car:
id: UUID
type: CarTypes
owner: str
def run(self):
...
def idk_some_car_stuf(self, speed):
...
The class Car implements the domain rules referring to Car, and the application rules (ie, acces DB to load Car, access external APIs, put messages on queues, logs, etc) are implemented in a service class CarService:
class ServiceCar:
def __init__(self, car_id: UUID):
self._car = CarRepository.get(car_id)
def run(self):
log.info('Car is about to run')
self._car.run()
if self._car.type == CarTypes.SUV:
suvAPI.suv_is_running(self._car)
elif self._car.type == CarTypes.SPORT:
...
rabbitmq.publish({'car': self._car.__dict__, 'message': ...})
The problem is that different car types can have different application rule types (eg calling different external APIs, etc.) and since I want to follow the Open-Closed principle, I dont want to implements this ifs, so I choose to segregate CarService by CarTypes like this:
class CarService(ABC):
#abstractmethod
def run(self) -> None:
...
class SUVCarService(CarService):
''' Specific implementation here, following CarService interface'''
...
class SportCarService(CarService):
''' Specific implementation here, following CarService interface'''
...
class CarServiceFactory:
#classmethod
def build(cls, car_id: UUID) -> CarService:
car = CarRepository.get(car_id)
klass: CarService = SUVCarService if car.type == 'SUV' else SportCarService
return klass(car)
That is my current implementation (oc I used an generic and simples example here ) but im not satisfied, what I really want is to use Metaclasses to build the specific (ie SUVCarService and SportCarService). So, instead my controllers call something like this:
def controller_run(body):
service = CarServiceFactory.build(body['car_id'])
service.run()
...
It would be call something like:
def controller_run(body):
service = CarService(car_id=body['car_id'])
# This CarService calls return the specific class, so
# if car.type == 'suv' then type(service) == SUVCarService
service.run()
...
But the python documentation about metaclasses are confuse to me, (idk if I need to use __new__ method from the metaclass itself, or __prepare__ ).
A metaclass could be used there to automatically instantiate a "Car" to the appropriate subclass.
But maybe it would be complicating things beyond what is needed.
What is more bureaucratic than necessary in your examples is that the car service factory has no need to be a class on its own - it can be a simple function.
So, for a function-factory:
def car_service_factory(cls, car_id: UUID) -> CarService:
car = CarRepository.get(car_id)
# klass: CarService = SUVCarService if car.type == 'SUV' else SportCarService
# nice place to use the new pattern matching construct in Python 3.10. Unless you
# need to support new classes in a dynamic way (i.e. not all car types
#are hardcoded)
match car.type:
case "SUV":
klass = SuvCarService
case _:
klass = SportsCarService
return klass(car)
This is "pythonland": it is not "ugly" to use plain functions where you don't need to artificially create a class.
If you want a metaclass, you could move the factory logic into the metaclass __call__ method. It then could select the appropriate subclass before instantiating it. But it is rather subjective if it is more "elegant", and it is certainly less maintainable - as metaclasses are an advanced topic a lot of programmers don't grasp in full. Ultimately, you could get away with a plain Python dictionary working as a Service class registry, keyed to the car types.
Since the question is about a metaclass anyway, here it goes. The only different thing is that it can take advantage of the __init__ method to keep a dynamic registry of all car Service classes. It could be derived from the class name, as a string - but I think it is less hacky to have an explicit type attribute on those as well.
from abc import ABCMeta
from typing import Union, Optional
from enum import Enum
class CarTypes(Enum):
SUV = 'suv'
SPORT = 'sport'
class Car:
...
class MetaCarService(ABCMeta):
service_registry = {}
def __init__(cls, name, bases, ns, **kw):
cls.__class__.service_registry[cls.type] = cls
return super().__init__(name, bases, ns, **kw)
def __call__(cls, car_or_id: Union[UUID, Car]) -> "CarService":
if not isinstance(car_or_id, Car):
car = CarRepository.get(car_id)
else:
car = car_id
# for hardcoded classses you may use your example code:
# cls: CarService = SUVCarService if car.type == 'SUV' else SportCarService
# For auto-discovery, you may do:
try:
cls = cls.__class__.service_registry[car.type.value]
except KeyError:
raise ValueError(f"No registered Service class for car type {car.type}" )
instance = super.__call__(cls, car)
return instance
class CarService(metaclass=MetaCarService):
type: Optional[CarTypes] = None
def __init__(self, car_or_id: Union[UUID, Car]):
# the annotation trick is a workaround so that you can use the UUID
# in your code, and the metaclass can pass the instantiated Car here.
# You could accept just the UUID and create a new car instance,
# disregarding the one build in the metaclass, of course
# (I think the annotation linter will require you to
# copy-paste the `isinstance(car_or_id, Car)` block here)
self.car = car_or_id
#abstractmethod
def run(self) -> None:
...
class SUVCarService(CarService):
''' Specific implementation here, following CarService interface'''
type = CarTypes.SUV
...
class SportCarService(CarService)
''' Specific implementation here, following CarService interface'''
type = CarTypes.SPORT
...
...
def controller_run(body):
service = CarService(body['car_id'])
service.run()
...

Struggling with Class Inheritance & super().__init__

Very new to Python, trying to create a game in which any number of armies can be created, but each army will pre-render the names of the soldiers.
I think I need to be using super init to really cut down on duplicate code, but I cannot for the life of me figure out how to make it work. From what I understand my class Army should be the Parent class, with RedArmy and Scout as subclasses. I'm just struggling to understand where the super().__init__() should come in?
class Army:
def __init__(self):
self.color = None
self.scoutname = None
self.demomanname = None
self.medicname = None
def train_scout(self, weapon):
return Scout(self.color, self.scoutname, weapon)
class RedArmy(Army):
def __init__(self):
self.color = "Red"
self.scoutname = "Yankee"
self.demomanname = "Irish"
self.medicname = "Dutch"
class BlueArmy(Army):
pass
class Scout:
specialization = "fast captures"
def __init__(self, color, scoutname, weapon):
self.color = color
self.scoutname = scoutname
self.weapon = weapon
def introduce(self):
return (f'Hi I\'m {self.scoutname}, I do {self.specialization} and I wield a {self.weapon}')
my_army = RedArmy()
soldier_1 = my_army.train_scout("baseball bat")
print(soldier_1.introduce())
Where to put the super().__init__ (if anywhere) depends on the specifics of your class hierarchy.
Most commonly, if it matters where you put it, you want it at the very start of the subclass's __init__ method. This makes sure that all of the base-class variables are set up, all of its invariants are met, and all of its methods can be called by the rest of the subclass __init__ code.
In your case, it matters because you're setting the same attributes in the base class and the subclass. You obviously want the subclass version to be the one that takes, so it has to come after the default assignments, not before:
class RedArmy(Army):
def __init__(self):
super().__init__()
self.color = "Red"
self.scoutname = "Yankee"
self.demomanname = "Irish"
self.medicname = "Dutch"
However, it's worth considering whether you really want the base class to set these variables to None in the first place.
I assume that in your real code, BlueArmy isn't just going to pass, but is instead going to do the same thing as RedArmy, replacing all of those values with some strings.
Also, the rest of your code is presumably going to assume that there are valid strings there, not None. An exception like TypeError: '<' not supported between instances of 'NoneType' and 'str' is harder to debug than AttributeError: 'GreenArmy' object has no attribute 'scoutname', not easier, so why not just leave the defaults out? Then you can eliminate Army.__init__ entirely, and you don't have to worry about calling super in the subclass initializers in the first place.
Or, alternatively, you could have Army.__init__ take parameters that are used to assign the values, and have the subclasses call super().__init__("Red", "Yankee", "Irish", "Dutch"). Then, Army() will raise a TypeError instead of creating an invalid Army instance. Or you could make an #abstractmethod named self._setup() that Army.__init__ calls and expects each subclass to provide, so Army() will raise an even more meaningful TypeError about instantiating an abstract class. These refinements make it easier to debug your Army subclasses—if you just have two of them, they may just be a waste of time, but if you have a bunch of them, which will be developed by a variety of people or over a long period of time, it might be worth it.
Passing values as arguments makes the most sense if you want your classes to take advantage of super and init:
class Army:
def __init__(self, color=None, scoutname=None, demomanname=None,
medicname=None):
self.color = color
self.scoutname = scoutname
self.demomanname = demomanname
self.medicname = medicname
def train_scout(self, weapon):
return Scout(self.color, self.scoutname, weapon)
class RedArmy(Army):
def __init__(self, color="Red", scoutname="Yankee", demomanname="Irish",
medicname="Dutch"):
super().__init__(color, scoutname, demomanname, medicname)
class Scout:
specialization = "fast captures"
def __init__(self, color, scoutname, weapon):
self.color = color
self.scoutname = scoutname
self.weapon = weapon
def introduce(self):
return (
f'Hi I\'m {self.scoutname}, I do {self.specialization} and I wield '
f'a {self.weapon}')
my_army = RedArmy()
soldier_1 = my_army.train_scout("baseball bat")
print(soldier_1.introduce())

Python - Getting subclass from input. Do I have to write a separate function?

I'm working in Python 2.7.8. What follows is a slight variant of the problem I'm working on.
I have a large number of custom classes that I've written where the inheritance is like a tree. The behavior is well encapsulated by the following example:
import random
class Animal(object):
def __init__(self, name):
self.name = name
self.can_own_pets = False #most Animals cannot own pets
self.get_features()
def give_pet(self, pet):
if not self.can_own_pets:
print(self.name+' cannot own a pet!')
else:
self.pets.append(pet)
def is_hungry(self):
return random.choice([True, False])
def get_features(self):
"""
In some classes, get features will be a function
that uses self.name to extract features.
In my problem, the features are extracted
with regular expressions that are determined by
by the class.
"""
pass
class Human(Animal):
def __init__(self, name):
super(Human, self).__init__(name)
self.can_own_pets = True
self.pets = []
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)
def bark(self):
print 'WOOF'
def get_features(self):
if 'chihuahua' in self.name:
self.is_annoying = True
elif 'corgi' in self.name:
self.adorable = True
My program needs to take in a large number of animals and delegate them to the correct classes -- I need the correct attributes and methods. What I would like to do is modify the Animal constructor so that if the name argument is something like "Finn the Dog" or "Jake the Human", it (the constructor) returns an instance of the class "Dog" or "Human", complete with the appropriate methods and attributes. Now, I know that I could easily write a function that takes a string and class as arguments, constructs a dictionary where the keys are the names of the subclasses of the given class, looks up the element of the dictionary that is contained in the string, and returns an object of that class. My question is whether or not there is a way to code this into the Animal class itself, which seems more elegant to me (as well as easier to maintain).
Here's an implementation --
def _get_all_subclasses(cls):
for scls in cls.__subclasses__():
yield scls
for scls in _get_all_subclasses(scls):
yield scls
class Animal(object):
#staticmethod
def from_string(s):
for cls in _get_all_subclasses(Animal):
# Somehow pick the class based on the string... This is a really simple example...
if cls.__name__ in s:
return cls()
raise ValueError('Bummer. Animal has not been discovered.')
class Dog(Animal):
pass
class Cat(Animal):
pass
class Lion(Cat):
pass
print Animal.from_string('is a Dog')
print Animal.from_string('is a Cat')
print Animal.from_string('Lions!!!')
print Animal.from_string('Lockness Monster')
There are limitations here
All of the constructors need to be pretty much the same which means that Cat.__init__ needs to basically do the same thing that Human.__init__ does.
After you create the instance, your code needs to have logic to handle Cat, Human, Dog, etc. In some cases that's Ok (e.g. the code really only cares that it is working with an Animal), but frequently it isn't (after all, Cats can walk on fences, but Humans can't).
Generally, the principle that I like to live by is to try to make the inputs to my functions permissive (is it a list or a tuple? Who cares! Duck Typing FTW!) but to try to have really well defined outputs. I think that this makes interfaces easier to use in the long haul and the code that I wrote above would probably not pass a code review if I was the reviewer :-).
To build upon mgilson's answer
You can override the __new__ method so that you can instantiate the classes like normal without a static method.
class Animal(object):
#classmethod
def _get_all_subclasses(cls):
for scls in cls.__subclasses__():
yield scls
for scls in scls._get_all_subclasses():
yield scls
def __new__(cls, name):
cls_ = cls
for subcls in Animal._get_all_subclasses():
if subcls.__name__ in name:
cls_ = subcls
break
instance = object.__new__(cls_)
if not issubclass(cls_, cls):
instance.__init__(name)
return instance

Is there a "pythonic" approach to required properties (OOP)?

I'm struggling to find a "pythonic" approach to the following class organization:
I have a base class with properties initialized in its constructor, for example:
class Animal(object):
def __init__(self, class_, species, is_domesticated):
self.class_ = class_
self.species = species
self.is_domesticated = is_domesticated
Then, when I subclass, I would like to "hard-code" one or more of these properties, like so:
class Mammal(Animal):
def __init__(self, species, is_domesticated):
Animal.__init__(self, 'Mammal', species, is_domesticated)
A Mammal is thus instantiated like so:
monkey = Mammal('Primate', false)
The problem is, I would like to use *args so as to leave any derived classes alone when altering the base class definition. Thus the definition of Mammal becomes:
class Mammal(Animal):
def __init__(self, *args):
Animal.__init(self, *(args + (class_='Mammal',)))
Which (needless to say) looks horrible. Some tips would be appreciated =)
If you only have a fixed set of arguments in the base class, there isn't much need to worry about variable arguments. Just do what you did in your first example and it's fine. If you want to be able to randomly add arguments to the base class, but add them as positional arguments and without defaults, there's no hope; you can't just change the base class willy-nilly and expect all derived classes to keep working.
However, there is a fairly common intermediate case where you might have a large set of attributes, various combinations of which may be passed to any class in the hierarchy. You might want to add new arguments to the base class, but they'll have defaults so that derived classes don't need to know about them explicitly; they'll just gracefully degrade to the base-class default. In such a case it's usually a better idea to use **kwargs rather than *args.
class Animal(object):
def __init__(self, **kwargs):
self.class_ = kwargs['class_']
self.species = kwargs['species']
# etc.
class Mammal(Animal):
def __init__(self, **kwargs):
Animal.__init__(self, class_="Mammal", **kwargs)
This requires the arguments to passed by keyword:
>>> Animal(class_='Fish', species='barracuda', is_domesticated=False)
4: <__main__.Animal object at 0x0177ABF0>
>>> Mammal(species="monkey", is_domesticated=False)
5: <__main__.Mammal object at 0x0177AFB0>
. . . but this is better if there are a lot of them, because no one will remember which order to pass them in if you have 10 different things getting passed in positionally. It also means that you can add new arguments easily; no one has to know where in the list to put the new ones, they can just add them anywhere by keyword.
In Python 2 you have to manually extract the kwargs as I did above. In Python 3 you can use keyword-only arguments to make this even easier.
Well, why don't you just do what you said you want? Make Mammal.__init__() take a *args argument, then use that. Here's the code:
class Animal(object):
def __init__(self, class_, species, is_domesticated):
self.class_ = class_
self.species = species
self.is_domesticated = is_domesticated
def __str__(self):
s_dom = "dom" if self.is_domesticated else "wild"
return ("Animal(%s, %s, %s)" % (self.class_, self.species, s_dom))
class Mammal(Animal):
def __init__(self, *args):
Animal.__init__(self, 'Mammal', *args)
cat = Mammal("cat", True)
print(cat)
lion = Mammal("lion", False)
print(lion)
The output:
Animal(Mammal, cat, dom)
Animal(Mammal, lion, wild)

What's an example use case for a Python classmethod?

I've read What are Class methods in Python for? but the examples in that post are complex. I am looking for a clear, simple, bare-bones example of a particular use case for classmethods in Python.
Can you name a small, specific example use case where a Python classmethod would be the right tool for the job?
Helper methods for initialization:
class MyStream(object):
#classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
#classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...
Well __new__ is a pretty important classmethod. It's where instances usually come from
so dict() calls dict.__new__ of course, but there is another handy way to make dicts sometimes which is the classmethod dict.fromkeys()
eg.
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
I don't know, something like named constructor methods?
class UniqueIdentifier(object):
value = 0
def __init__(self, name):
self.name = name
#classmethod
def produce(cls):
instance = cls(cls.value)
cls.value += 1
return instance
class FunkyUniqueIdentifier(UniqueIdentifier):
#classmethod
def produce(cls):
instance = super(FunkyUniqueIdentifier, cls).produce()
instance.name = "Funky %s" % instance.name
return instance
Usage:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
The biggest reason for using a #classmethod is in an alternate constructor that is intended to be inherited. This can be very useful in polymorphism. An example:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
#classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
Notice that Shape is an abstract class that defines a classmethod from_square, since Shape is not really defined, it does not really know how to derive itself from a Square so it simply returns a default instance of the class.
Inherited classes are then allowed to define their own versions of this method:
class Square(Shape):
def __init__(self, side=10):
self.side = side
#classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
#classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init__(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
#classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
The usage allows you to treat all of these uninstantiated classes polymorphically
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
This is all fine and dandy you might say, but why couldn't I just use as #staticmethod to accomplish this same polymorphic behavior:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#staticmethod
def from_square(square):
return Circle(radius=square.length/2)
The answer is that you could, but you do not get the benefits of inheritance because Circle has to be called out explicitly in the method. Meaning if I call it from an inherited class without overriding, I would still get Circle every time.
Notice what is gained when I define another shape class that does not really have any custom from_square logic:
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
Here you can leave the #classmethod undefined and it will use the logic from Shape.from_square while retaining who cls is and return the appropriate shape.
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)
I find that I most often use #classmethod to associate a piece of code with a class, to avoid creating a global function, for cases where I don't require an instance of the class to use the code.
For example, I might have a data structure which only considers a key valid if it conforms to some pattern. I may want to use this from inside and outside of the class. However, I don't want to create yet another global function:
def foo_key_is_valid(key):
# code for determining validity here
return valid
I'd much rather group this code with the class it's associated with:
class Foo(object):
#classmethod
def is_valid(cls, key):
# code for determining validity here
return valid
def add_key(self, key, val):
if not Foo.is_valid(key):
raise ValueError()
..
# lets me reuse that method without an instance, and signals that
# the code is closely-associated with the Foo class
Foo.is_valid('my key')
Another useful example of classmethod is in extending enumerated types. A classic Enum provides symbolic names which can be used later in the code for readability, grouping, type-safety, etc. This can be extended to add useful features using a classmethod. In the example below, Weekday is an enuerated type for the days of the week. It has been extended using classmethod so that instead of keeping track of the weekday ourselves, the enumerated type can extract the date and return the related enum member.
from enum import Enum
from datetime import date
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
#
#classmethod
def from_date(cls, date):
return cls(date.isoweekday())
Weekday.from_date(date.today())
<Weekday.TUESDAY: 2>
Source: https://docs.python.org/3/howto/enum.html
in class MyClass(object):
'''
classdocs
'''
obj=0
x=classmethod
def __init__(self):
'''
Constructor
'''
self.nom='lamaizi'
self.prenom='anas'
self.age=21
self.ville='Casablanca'
if __name__:
ob=MyClass()
print(ob.nom)
print(ob.prenom)
print(ob.age)
print(ob.ville)

Categories

Resources