Python inheritance: convert from Base class to Derived class - python

I'm still pretty new to Python, so bear with me. Here is my problem:
I have a base class, lets call it a sports game:
class Game:
def __init__(self):
self.home_team = None
self.away_team = None
and I have multiple derived classes for each sport, but lets use baseball as an example:
class BaseballGame(Game):
def __init__(self):
self.home_pitcher = None
self.away_pitcher = None
So far everything is good. However I have another utility function in a separate python module which will generate and populate a list of all the games being played on a given day for that sport.
def fetch_game_data:
games = []
games_found_online = code_that_fetches_online_games
for online_game in games_found_online:
new_game = Game()
new_game.home_team = ...
new_game.away_team = ...
games.append(new_game)
return games
Its obviously much more complicated than this with a lot of parsing using BeautifulSoup, but you get the point. My problem is that this function returns a list of the Base class, but I need a list of the Derived class. The derived classes will be the ones calling this function to populate a list and operate on it. The way I see it, I have two options:
I could implement a dreaded circular dependency and have the fetch_game_data function know about all of the derived classes and call the derived class constructors instead of the base class constructors. The derived classes already need to import the fetch_data module, but now the fetch_data module will have to import all of the derived classes to know about their constructors. And what makes it worse is that the fetch_data module won't have any need to touch any of the derived class fields - it only populates base class fields. The circular dependency is JUST so I can create the objects.
I could implement code that downcasts a Base class Game to a Derived class Game (like BaseballGame). Then, when the fetch_game_data function returns all of the games I can just convert them all to a Derived class object and continue on my way. Unfortunately I haven't seen much in the way of how to implement this. I tried just changing the class variable, but then the code complains because Derived class variables don't exist.
Another option I considered, but quickly fell apart, was to send an existing list of derived class objects into the fetch_game_data function, and instead of creating new Game objects it would just populate existing ones. The problem is that I won't know how many game objects I need. The fetch_game_data function determines how many games are needed by parsing the webpage. I suppose I could send in the max number of games but using number_of_teams/2, but what if there is a double-header in baseball? This quickly falls apart. I suppose I could write a function that will fetch the game data and just return the number of games for the day. Then I could populate a list of Derived games that size and send it in to be populated. But I would have to fetch all the webpage data AGAIN and parse it AGAIN to populate the list.
Nothing but bad options! I'm hoping there is a simple and elegant solution that has just eluded me thus far. I'm open to any suggestions, including a redesign if it makes sense.
Thanks!

I am porting existing code from c++ and I encountered a similar problem.
I have a generic class X and type specific classes e.g. XInt, XStr etc. There is more differences between these classes than just the type of the value. In c++ it was easy: I have virtual X::compare(X const& other).
It is overridden in XInt. Inside the overridden method I first handle cases where the 'other' is not XInt and then do static_cast<XInt const&>(other).
It is clearly impossible in python. So here is my solution. I added a non-virtual non-public function to do actual comparison to XInt and did not annotate the type of the parameter:
def _compare(self, other) -> int:
<do-actual-comparison>
def compare(self, other: X) -> int:
<handle cases where other is not XInt>
return self._compare_worker(other)
Did not test it yet but mypy does not complain and it seems that it will work due to duck typing in python. Maybe something similar will work for you.

You can convert a class of instance after it is initiated, see example below:
class A:
def __repr__(self):
return "class A"
def convert(self):
'convert A to B class'
self.__class__ = B
def hello(self):
print('hello from A')
class B(A):
""
def __repr__(self):
return "class B"
def hello(self):
print('hello from B')
a = A()
print(a)
a.hello()
a.convert()
print(a)
a.hello()
# output:
>>> "class A"
>>> "hello from A"
>>> "class B"
>>> "hello from B"
In your case, you can convert the class Game to whatever subclass you want after the instance is created.

Python cannot cast an object to another class (even subclass).
You must use concrete class when you create the game object. It can be done in a factory method (e.g. create_game), like this:
def create_game(online_game):
if online_game.type == 'baseball':
return BaseballGame()
else:
return Game()
def fetch_game_data:
games = []
games_found_online = code_that_fetches_online_games
for online_game in games_found_online:
new_game = create_game(online_game)
new_game.home_team = ...
new_game.away_team = ...
games.append(new_game)
return games

Related

Does it ever make sense to write 2 classes with identical names in the same python program?

Are there any scenarios where it would make sense to write two python classes in the same program with the same name using different parameters? I was thinking through this program, but my 2nd test class will just overwrite the first. Is this always the case?
class test:
def __init__(self):
print("first class")
def oneplus(self, x):
print(x + 1)
class test:
def __init__(self):
print("second class")
def twoplus(self, x):
print(x + 2)
t = test()
t.twoplus(1)
will just result in using the 2nd instance:
second class
3
yes, if you define a class with the same name as an already existing class, it will override the definition.
BUT existing instances of the first class will still behave as usual.
small example:
class test:
def __init__(self):
print("first class")
def oneplus(self, x):
print(x+1)
t1 = test()
class test:
def __init__(self):
print("second class")
def twoplus(self, x):
print(x+2)
t2=test()
t1.oneplus(1)
t2.twoplus(1)
Output:
first class
second class
2
3
If you never use the first class, IDEs like PyCharm will even warn you about this:
A program may consist of more than one module. In that case, it can make a lot of sense to have a class with the same name. For example if you have a feature that works differently in Windows vs Linux, you can have a module implementing the windows-specific stuff, and a module implementing the Linux-specific stuff. Both would have classes with identical names. In your code, you could do
if os.name == nt:
from windows_support import Feature
else:
from linux_support import Feature
This could be done for any external influence, not just the platform.
If you have only a small number of differences, usually ones that are a subset of the module in question, you can have two classes with identical names in different branches of an if statement. For example:
if os.name == 'nt':
class Feature:
...
else:
class Feature:
...
The statements def, class, and most forms of import are assignments. It makes just as much sense to assign a different value to a name under different conditions as it does a different class or function. After all, classes are just objects in python.
That being said, all the examples above work best if both options implement the same public interface.
An example of different classes that unconditionally have the same name in the same namespace that serves a real life purpose is forward declaration for type hints. Until PEP 563 introduced delayed evaluation of annotations in Python 3.7, it was impossible to use a class name in an annotation until it was assigned. By extension, that meant that methods of a class could not accept or return instances of the class they were defined in, and circular references between classes were not supported without a workaround. That workaround was to define an empty definition of a class with the same name, before the classes that would be using it in type hints. This would actually keep a reference to the forward-declared throwaway class around, which was one of the motivations for PEP 563.
As mentioned above, the second assignment of test will override the first assignment. Basically, when a class is assigned in Python it is stored in memory with a type, value, and reference count. In this case the first assignment of "Test" creates a python object (Test1) with a reference count of 1 and the second assignment of "Test" creates another python object (Test2) with a reference count of 1, but "Test" is no longer referencing the original python object (Test1) so its reference count decreases to 0.
Example of names in Python.
Great resource for python objects: https://realpython.com/pointers-in-python/
Unless you plan on making the system recognize the second definition only, then making two variables with the same name will not make a difference.
You can add 1 more method in Test class,
class test:
def __init__(self):
print("first class")
def oneplus(self, x):
print(x + 1)
def twoplus(self, x):
print(x + 2)
t = test()
t.oneplus(1)
t.twoplus(1)

How to Inherit multiple classes in python dynamically [duplicate]

This article has a snippet showing usage of __bases__ to dynamically change the inheritance hierarchy of some Python code, by adding a class to an existing classes collection of classes from which it inherits. Ok, that's hard to read, code is probably clearer:
class Friendly:
def hello(self):
print 'Hello'
class Person: pass
p = Person()
Person.__bases__ = (Friendly,)
p.hello() # prints "Hello"
That is, Person doesn't inherit from Friendly at the source level, but rather this inheritance relation is added dynamically at runtime by modification of the __bases__attribute of the Person class. However, if you change Friendly and Person to be new style classes (by inheriting from object), you get the following error:
TypeError: __bases__ assignment: 'Friendly' deallocator differs from 'object'
A bit of Googling on this seems to indicate some incompatibilities between new-style and old style classes in regards to changing the inheritance hierarchy at runtime. Specifically: "New-style class objects don't support assignment to their bases attribute".
My question, is it possible to make the above Friendly/Person example work using new-style classes in Python 2.7+, possibly by use of the __mro__ attribute?
Disclaimer: I fully realise that this is obscure code. I fully realize that in real production code tricks like this tend to border on unreadable, this is purely a thought experiment, and for funzies to learn something about how Python deals with issues related to multiple inheritance.
Ok, again, this is not something you should normally do, this is for informational purposes only.
Where Python looks for a method on an instance object is determined by the __mro__ attribute of the class which defines that object (the M ethod R esolution O rder attribute). Thus, if we could modify the __mro__ of Person, we'd get the desired behaviour. Something like:
setattr(Person, '__mro__', (Person, Friendly, object))
The problem is that __mro__ is a readonly attribute, and thus setattr won't work. Maybe if you're a Python guru there's a way around that, but clearly I fall short of guru status as I cannot think of one.
A possible workaround is to simply redefine the class:
def modify_Person_to_be_friendly():
# so that we're modifying the global identifier 'Person'
global Person
# now just redefine the class using type(), specifying that the new
# class should inherit from Friendly and have all attributes from
# our old Person class
Person = type('Person', (Friendly,), dict(Person.__dict__))
def main():
modify_Person_to_be_friendly()
p = Person()
p.hello() # works!
What this doesn't do is modify any previously created Person instances to have the hello() method. For example (just modifying main()):
def main():
oldperson = Person()
ModifyPersonToBeFriendly()
p = Person()
p.hello()
# works! But:
oldperson.hello()
# does not
If the details of the type call aren't clear, then read e-satis' excellent answer on 'What is a metaclass in Python?'.
I've been struggling with this too, and was intrigued by your solution, but Python 3 takes it away from us:
AttributeError: attribute '__dict__' of 'type' objects is not writable
I actually have a legitimate need for a decorator that replaces the (single) superclass of the decorated class. It would require too lengthy a description to include here (I tried, but couldn't get it to a reasonably length and limited complexity -- it came up in the context of the use by many Python applications of an Python-based enterprise server where different applications needed slightly different variations of some of the code.)
The discussion on this page and others like it provided hints that the problem of assigning to __bases__ only occurs for classes with no superclass defined (i.e., whose only superclass is object). I was able to solve this problem (for both Python 2.7 and 3.2) by defining the classes whose superclass I needed to replace as being subclasses of a trivial class:
## T is used so that the other classes are not direct subclasses of object,
## since classes whose base is object don't allow assignment to their __bases__ attribute.
class T: pass
class A(T):
def __init__(self):
print('Creating instance of {}'.format(self.__class__.__name__))
## ordinary inheritance
class B(A): pass
## dynamically specified inheritance
class C(T): pass
A() # -> Creating instance of A
B() # -> Creating instance of B
C.__bases__ = (A,)
C() # -> Creating instance of C
## attempt at dynamically specified inheritance starting with a direct subclass
## of object doesn't work
class D: pass
D.__bases__ = (A,)
D()
## Result is:
## TypeError: __bases__ assignment: 'A' deallocator differs from 'object'
I can not vouch for the consequences, but that this code does what you want at py2.7.2.
class Friendly(object):
def hello(self):
print 'Hello'
class Person(object): pass
# we can't change the original classes, so we replace them
class newFriendly: pass
newFriendly.__dict__ = dict(Friendly.__dict__)
Friendly = newFriendly
class newPerson: pass
newPerson.__dict__ = dict(Person.__dict__)
Person = newPerson
p = Person()
Person.__bases__ = (Friendly,)
p.hello() # prints "Hello"
We know that this is possible. Cool. But we'll never use it!
Right of the bat, all the caveats of messing with class hierarchy dynamically are in effect.
But if it has to be done then, apparently, there is a hack that get's around the "deallocator differs from 'object" issue when modifying the __bases__ attribute for the new style classes.
You can define a class object
class Object(object): pass
Which derives a class from the built-in metaclass type.
That's it, now your new style classes can modify the __bases__ without any problem.
In my tests this actually worked very well as all existing (before changing the inheritance) instances of it and its derived classes felt the effect of the change including their mro getting updated.
I needed a solution for this which:
Works with both Python 2 (>= 2.7) and Python 3 (>= 3.2).
Lets the class bases be changed after dynamically importing a dependency.
Lets the class bases be changed from unit test code.
Works with types that have a custom metaclass.
Still allows unittest.mock.patch to function as expected.
Here's what I came up with:
def ensure_class_bases_begin_with(namespace, class_name, base_class):
""" Ensure the named class's bases start with the base class.
:param namespace: The namespace containing the class name.
:param class_name: The name of the class to alter.
:param base_class: The type to be the first base class for the
newly created type.
:return: ``None``.
Call this function after ensuring `base_class` is
available, before using the class named by `class_name`.
"""
existing_class = namespace[class_name]
assert isinstance(existing_class, type)
bases = list(existing_class.__bases__)
if base_class is bases[0]:
# Already bound to a type with the right bases.
return
bases.insert(0, base_class)
new_class_namespace = existing_class.__dict__.copy()
# Type creation will assign the correct ‘__dict__’ attribute.
del new_class_namespace['__dict__']
metaclass = existing_class.__metaclass__
new_class = metaclass(class_name, tuple(bases), new_class_namespace)
namespace[class_name] = new_class
Used like this within the application:
# foo.py
# Type `Bar` is not available at first, so can't inherit from it yet.
class Foo(object):
__metaclass__ = type
def __init__(self):
self.frob = "spam"
def __unicode__(self): return "Foo"
# … later …
import bar
ensure_class_bases_begin_with(
namespace=globals(),
class_name=str('Foo'), # `str` type differs on Python 2 vs. 3.
base_class=bar.Bar)
Use like this from within unit test code:
# test_foo.py
""" Unit test for `foo` module. """
import unittest
import mock
import foo
import bar
ensure_class_bases_begin_with(
namespace=foo.__dict__,
class_name=str('Foo'), # `str` type differs on Python 2 vs. 3.
base_class=bar.Bar)
class Foo_TestCase(unittest.TestCase):
""" Test cases for `Foo` class. """
def setUp(self):
patcher_unicode = mock.patch.object(
foo.Foo, '__unicode__')
patcher_unicode.start()
self.addCleanup(patcher_unicode.stop)
self.test_instance = foo.Foo()
patcher_frob = mock.patch.object(
self.test_instance, 'frob')
patcher_frob.start()
self.addCleanup(patcher_frob.stop)
def test_instantiate(self):
""" Should create an instance of `Foo`. """
instance = foo.Foo()
The above answers are good if you need to change an existing class at runtime. However, if you are just looking to create a new class that inherits by some other class, there is a much cleaner solution. I got this idea from https://stackoverflow.com/a/21060094/3533440, but I think the example below better illustrates a legitimate use case.
def make_default(Map, default_default=None):
"""Returns a class which behaves identically to the given
Map class, except it gives a default value for unknown keys."""
class DefaultMap(Map):
def __init__(self, default=default_default, **kwargs):
self._default = default
super().__init__(**kwargs)
def __missing__(self, key):
return self._default
return DefaultMap
DefaultDict = make_default(dict, default_default='wug')
d = DefaultDict(a=1, b=2)
assert d['a'] is 1
assert d['b'] is 2
assert d['c'] is 'wug'
Correct me if I'm wrong, but this strategy seems very readable to me, and I would use it in production code. This is very similar to functors in OCaml.
This method isn't technically inheriting during runtime, since __mro__ can't be changed. But what I'm doing here is using __getattr__ to be able to access any attributes or methods from a certain class. (Read comments in order of numbers placed before the comments, it makes more sense)
class Sub:
def __init__(self, f, cls):
self.f = f
self.cls = cls
# 6) this method will pass the self parameter
# (which is the original class object we passed)
# and then it will fill in the rest of the arguments
# using *args and **kwargs
def __call__(self, *args, **kwargs):
# 7) the multiple try / except statements
# are for making sure if an attribute was
# accessed instead of a function, the __call__
# method will just return the attribute
try:
return self.f(self.cls, *args, **kwargs)
except TypeError:
try:
return self.f(*args, **kwargs)
except TypeError:
return self.f
# 1) our base class
class S:
def __init__(self, func):
self.cls = func
def __getattr__(self, item):
# 5) we are wrapping the attribute we get in the Sub class
# so we can implement the __call__ method there
# to be able to pass the parameters in the correct order
return Sub(getattr(self.cls, item), self.cls)
# 2) class we want to inherit from
class L:
def run(self, s):
print("run" + s)
# 3) we create an instance of our base class
# and then pass an instance (or just the class object)
# as a parameter to this instance
s = S(L) # 4) in this case, I'm using the class object
s.run("1")
So this sort of substitution and redirection will simulate the inheritance of the class we wanted to inherit from. And it even works with attributes or methods that don't take any parameters.

Python 3 dynamically assign base class

I am writing a simple chess program to practice my OOP in python 3 and was wondering how to dynamically change (before class creation) the base class for a class definition. My class structure is this.
abstract Piece class -> various derived pieces
Board class, has a composite of derived Pieces, and 8x8 matrix, and some methods
abstract Interface class -> CLI or
abstract Interface class -> GUI (also subclassing Tkinter)
Game class (for processing the game logic and main loop), which currently has a Board class member.
I initially implemented the Game class as having an interface data member that is defined during init but I'm finding myself sending a lot of the other internal Game data to the Interface composite member. I feel it would be more elegant to have the Game class be a subclass of either Interface subclass so the it could access their methods directly (and make them abstract).
However I want a version of the Game class that can do this dynamically so that I don't have to code it twice or inherit from both and make runtime decisions on which base class to use. I've currently done this by nesting the Game class inside a function like so.
def Game(ui):
class Game(ui):
...
return Game()
The crummy naming is part of the reason I don't like this solution. I want to be able to call the Game class on its own without explicitly using or acknowledging that I'm doing anything out of the ordinary.
Is there a way to do this with a metaclass or a class decorator? I have only been able to get them to affect class attributes, not the parent classes.
The class statement is "syntactic sugar" for
type(name, bases, dict)
You can create such a dynamic class using type like this
>>> class ui():
... def start(self): print("Started!")
...
>>> Game = type("Game", (ui,), {})
>>> game = Game()
>>> game.start()
Started!
You could use a very simple metclass here, but that's overkill. You can just swap out which class you're using as the base class based on whatever condition you want:
>>> class Foo: pass
...
>>> class Bar: pass
...
>>> x = 3
>>> class Game(Foo if x < 3 else Bar):pass
...
>>> Game.__bases__
(<class '__main__.Bar'>,)
Note that this isn't really any different than the formalism you have. However, if I was to use your code, I wouldn't create the Game class and the instance all in the function. I would do something like:
def Game_Factory(base):
class Game(base):
...
return Game
Game1 = Game_Factory(base1)
Game2 = Game_Factory(base2)
game1_instance = Game1()
game2_instance = Game2()
This gives you much easier access to the Game class (rather than needing to inspect an instance to get it).

Python Instantiating SubClasses

I wrote the following code trying to figure out how to instantiate the subclasses within the main class.. I came up with something that doesn't feel right.. at least for me.
Is there something wrong with this type of instancing? Is there a better way to call subclasses?
class Family():
def __init__(self):
self.Father = self.Father(self)
self.Mother = self.Mother(self)
class Father():
def __init__(self, instance = ''):
self = instance if instance != '' else self
print self
def method(self):
print "Father Method"
def fatherMethod(self):
print "Father Method"
class Mother():
def __init__(self, instance = ''):
self = instance if instance != '' else self
print self
def method(self):
print "Mother Method"
def motherMethod(self):
print "Mother Method"
if __name__ == "__main__":
Family = Family()
Family.Father.method()
Family.Mother.method()
What you've defined there are not (in Python terminology at least) subclasses - they're inner classes, or nested classes. I'm guessing that this isn't actually what you were trying to achieve, but I'm not sure what you did actually want - but here are my four best guesses:
A subclass is where the class inheriting from another class is called a subclass. To make father a subclass of family, use the syntax class Father(Family):. What you've created here is actually called an Inner Class, not a subclass.
When you see something like Family.Father.method(), it often means Family is a module and Father is a class in that module. In Python, module basically means .py file. A module doesn't have an __init__ method, but all code at the top level of the module (such as the if __name__ ... line) gets executed when a module is imported.
Similarly, you could make Family a package - which in Python basically means a directory on the filesystem containing an __init__.py file. Father and Mother would then be modules or classes within the package
Possibly what you're trying to achieve is declare that an object of type Family always has a Father object and a Mother object. This doesn't require nested classes (in fact, nested classes are a completely bizarre way to do this). Just use:
>>> class Mother():
... def whoami(self):
... print "I'm a mother"
...
>>> class Father():
... def whoami(self):
... print "I'm a father"
...
>>> class Family():
... def __init__(self):
... self.mother = Mother()
... self.father = Father()
...
>>> f = Family()
>>> f.father.whoami()
I'm a father
>>> f.mother.whoami()
I'm a mother
>>>
Blergh.
Why are Father and Mother nested under Family? There's no reason to do this. Define them outside, then instantiate them inside.
I'm not sure exactly what you want to do. You may want to look into Descriptors, which are a way of defining sub-objects within a clss.
You are right, this code does not feel right. My questions would be ..
What are you trying to achieve? There is not need to define Father and Mother inside Family, they could be defined outside Family and aggregated into it. (Is it the fact, that Father and Mother should not be accessed outside of a Family? Python has no visibility modifiers, e.g. because of a principle that goes: 'we are all grown-up here', meaning that developers should be responsible and assume responsible handling of code ...)
Do you really need something like Class.Class.method? Beside the fact, that method lookups are a little costly, these kind of chains may indicate a wrong axis, meaning you're trying to take hold of functionality from a not very clearly designed point (sorry for being so blurry here.)

What is the purpose of class methods?

I'm teaching myself Python and my most recent lesson was that Python is not Java, and so I've just spent a while turning all my Class methods into functions.
I now realise that I don't need to use Class methods for what I would done with static methods in Java, but now I'm not sure when I would use them. All the advice I can find about Python Class methods is along the lines of newbies like me should steer clear of them, and the standard documentation is at its most opaque when discussing them.
Does anyone have a good example of using a Class method in Python or at least can someone tell me when Class methods can be sensibly used?
Class methods are for when you need to have methods that aren't specific to any particular instance, but still involve the class in some way. The most interesting thing about them is that they can be overridden by subclasses, something that's simply not possible in Java's static methods or Python's module-level functions.
If you have a class MyClass, and a module-level function that operates on MyClass (factory, dependency injection stub, etc), make it a classmethod. Then it'll be available to subclasses.
Factory methods (alternative constructors) are indeed a classic example of class methods.
Basically, class methods are suitable anytime you would like to have a method which naturally fits into the namespace of the class, but is not associated with a particular instance of the class.
As an example, in the excellent unipath module:
Current directory
Path.cwd()
Return the actual current directory; e.g., Path("/tmp/my_temp_dir"). This is a class method.
.chdir()
Make self the current directory.
As the current directory is process wide, the cwd method has no particular instance with which it should be associated. However, changing the cwd to the directory of a given Path instance should indeed be an instance method.
Hmmm... as Path.cwd() does indeed return a Path instance, I guess it could be considered to be a factory method...
Think about it this way: normal methods are useful to hide the details of dispatch: you can type myobj.foo() without worrying about whether the foo() method is implemented by the myobj object's class or one of its parent classes. Class methods are exactly analogous to this, but with the class object instead: they let you call MyClass.foo() without having to worry about whether foo() is implemented specially by MyClass because it needed its own specialized version, or whether it is letting its parent class handle the call.
Class methods are essential when you are doing set-up or computation that precedes the creation of an actual instance, because until the instance exists you obviously cannot use the instance as the dispatch point for your method calls. A good example can be viewed in the SQLAlchemy source code; take a look at the dbapi() class method at the following link:
https://github.com/zzzeek/sqlalchemy/blob/ab6946769742602e40fb9ed9dde5f642885d1906/lib/sqlalchemy/dialects/mssql/pymssql.py#L47
You can see that the dbapi() method, which a database backend uses to import the vendor-specific database library it needs on-demand, is a class method because it needs to run before instances of a particular database connection start getting created — but that it cannot be a simple function or static function, because they want it to be able to call other, supporting methods that might similarly need to be written more specifically in subclasses than in their parent class. And if you dispatch to a function or static class, then you "forget" and lose the knowledge about which class is doing the initializing.
I recently wanted a very light-weight logging class that would output varying amounts of output depending on the logging level that could be programmatically set. But I didn't want to instantiate the class every time I wanted to output a debugging message or error or warning. But I also wanted to encapsulate the functioning of this logging facility and make it reusable without the declaration of any globals.
So I used class variables and the #classmethod decorator to achieve this.
With my simple Logging class, I could do the following:
Logger._level = Logger.DEBUG
Then, in my code, if I wanted to spit out a bunch of debugging information, I simply had to code
Logger.debug( "this is some annoying message I only want to see while debugging" )
Errors could be out put with
Logger.error( "Wow, something really awful happened." )
In the "production" environment, I can specify
Logger._level = Logger.ERROR
and now, only the error message will be output. The debug message will not be printed.
Here's my class:
class Logger :
''' Handles logging of debugging and error messages. '''
DEBUG = 5
INFO = 4
WARN = 3
ERROR = 2
FATAL = 1
_level = DEBUG
def __init__( self ) :
Logger._level = Logger.DEBUG
#classmethod
def isLevel( cls, level ) :
return cls._level >= level
#classmethod
def debug( cls, message ) :
if cls.isLevel( Logger.DEBUG ) :
print "DEBUG: " + message
#classmethod
def info( cls, message ) :
if cls.isLevel( Logger.INFO ) :
print "INFO : " + message
#classmethod
def warn( cls, message ) :
if cls.isLevel( Logger.WARN ) :
print "WARN : " + message
#classmethod
def error( cls, message ) :
if cls.isLevel( Logger.ERROR ) :
print "ERROR: " + message
#classmethod
def fatal( cls, message ) :
if cls.isLevel( Logger.FATAL ) :
print "FATAL: " + message
And some code that tests it just a bit:
def logAll() :
Logger.debug( "This is a Debug message." )
Logger.info ( "This is a Info message." )
Logger.warn ( "This is a Warn message." )
Logger.error( "This is a Error message." )
Logger.fatal( "This is a Fatal message." )
if __name__ == '__main__' :
print "Should see all DEBUG and higher"
Logger._level = Logger.DEBUG
logAll()
print "Should see all ERROR and higher"
Logger._level = Logger.ERROR
logAll()
Alternative constructors are the classic example.
It allows you to write generic class methods that you can use with any compatible class.
For example:
#classmethod
def get_name(cls):
print cls.name
class C:
name = "tester"
C.get_name = get_name
#call it:
C.get_name()
If you don't use #classmethod you can do it with self keyword but it needs an instance of Class:
def get_name(self):
print self.name
class C:
name = "tester"
C.get_name = get_name
#call it:
C().get_name() #<-note the its an instance of class C
When a user logs in on my website, a User() object is instantiated from the username and password.
If I need a user object without the user being there to log in (e.g. an admin user might want to delete another users account, so i need to instantiate that user and call its delete method):
I have class methods to grab the user object.
class User():
#lots of code
#...
# more code
#classmethod
def get_by_username(cls, username):
return cls.query(cls.username == username).get()
#classmethod
def get_by_auth_id(cls, auth_id):
return cls.query(cls.auth_id == auth_id).get()
I think the most clear answer is AmanKow's one. It boils down to how u want to organize your code. You can write everything as module level functions which are wrapped in the namespace of the module i.e
module.py (file 1)
---------
def f1() : pass
def f2() : pass
def f3() : pass
usage.py (file 2)
--------
from module import *
f1()
f2()
f3()
def f4():pass
def f5():pass
usage1.py (file 3)
-------------------
from usage import f4,f5
f4()
f5()
The above procedural code is not well organized, as you can see after only 3 modules it gets confusing, what is each method do ? You can use long descriptive names for functions(like in java) but still your code gets unmanageable very quick.
The object oriented way is to break down your code into manageable blocks i.e Classes & objects and functions can be associated with objects instances or with classes.
With class functions you gain another level of division in your code compared with module level functions.
So you can group related functions within a class to make them more specific to a task that you assigned to that class. For example you can create a file utility class :
class FileUtil ():
def copy(source,dest):pass
def move(source,dest):pass
def copyDir(source,dest):pass
def moveDir(source,dest):pass
//usage
FileUtil.copy("1.txt","2.txt")
FileUtil.moveDir("dir1","dir2")
This way is more flexible and more maintainable, you group functions together and its more obvious to what each function do. Also you prevent name conflicts, for example the function copy may exist in another imported module(for example network copy) that you use in your code, so when you use the full name FileUtil.copy() you remove the problem and both copy functions can be used side by side.
Honestly? I've never found a use for staticmethod or classmethod. I've yet to see an operation that can't be done using a global function or an instance method.
It would be different if python used private and protected members more like Java does. In Java, I need a static method to be able to access an instance's private members to do stuff. In Python, that's rarely necessary.
Usually, I see people using staticmethods and classmethods when all they really need to do is use python's module-level namespaces better.
I used to work with PHP and recently I was asking myself, whats going on with this classmethod? Python manual is very technical and very short in words so it wont help with understanding that feature. I was googling and googling and I found answer -> http://code.anjanesh.net/2007/12/python-classmethods.html.
If you are lazy to click it. My explanation is shorter and below. :)
in PHP (maybe not all of you know PHP, but this language is so straight forward that everybody should understand what I'm talking about) we have static variables like this:
class A
{
static protected $inner_var = null;
static public function echoInnerVar()
{
echo self::$inner_var."\n";
}
static public function setInnerVar($v)
{
self::$inner_var = $v;
}
}
class B extends A
{
}
A::setInnerVar(10);
B::setInnerVar(20);
A::echoInnerVar();
B::echoInnerVar();
The output will be in both cases 20.
However in python we can add #classmethod decorator and thus it is possible to have output 10 and 20 respectively. Example:
class A(object):
inner_var = 0
#classmethod
def setInnerVar(cls, value):
cls.inner_var = value
#classmethod
def echoInnerVar(cls):
print cls.inner_var
class B(A):
pass
A.setInnerVar(10)
B.setInnerVar(20)
A.echoInnerVar()
B.echoInnerVar()
Smart, ain't?
Class methods provide a "semantic sugar" (don't know if this term is widely used) - or "semantic convenience".
Example: you got a set of classes representing objects. You might want to have the class method all() or find() to write User.all() or User.find(firstname='Guido'). That could be done using module level functions of course...
if you are not a "programmer by training", this should help:
I think I have understood the technical explanations above and elsewhere on the net, but I was always left with a question "Nice, but why do I need it? What is a practical, use case?". and now life gave me a good example that clarified all:
I am using it to control the global-shared variable that is shared among instances of a class instantiated by multi-threading module. in humane language, I am running multiple agents that create examples for deep learning IN PARALLEL. (imagine multiple players playing ATARI game at the same time and each saving the results of their game to one common repository (the SHARED VARIABLE))
I instantiate the players/agents with the following code (in Main/Execution Code):
a3c_workers = [A3C_Worker(self.master_model, self.optimizer, i, self.env_name, self.model_dir) for i in range(multiprocessing.cpu_count())]
it creates as many players as there are processor cores on my comp
A3C_Worker - is a class that defines the agent
a3c_workers - is a list of the instances of that class (i.e. each instance is one player/agent)
now i want to know how many games have been played across all players/agents thus within the A3C_Worker definition I define the variable to be shared across all instances:
class A3C_Worker(threading.Thread):
global_shared_total_episodes_across_all_workers = 0
now as the workers finish their games they increase that count by 1 each for each game finished
at the end of my example generation i was closing the instances but the shared variable had assigned the total number of games played. so when I was re-running it again my initial total number of episodes was that of the previous total. but i needed that count to represent that value for each run individually
to fix that i specified :
class A3C_Worker(threading.Thread):
#classmethod
def reset(cls):
A3C_Worker.global_shared_total_episodes_across_all_workers = 0
than in the execution code i just call:
A3C_Worker.reset()
note that it is a call to the CLASS overall not any INSTANCE of it individually. thus it will set my counter to 0 for every new agent I initiate from now on.
using the usual method definition def play(self):, would require us to reset that counter for each instance individually, which would be more computationally demanding and difficult to track.
What just hit me, coming from Ruby, is that a so-called class method and a so-called instance method is just a function with semantic meaning applied to its first parameter, which is silently passed when the function is called as a method of an object (i.e. obj.meth()).
Normally that object must be an instance but the #classmethod method decorator changes the rules to pass a class. You can call a class method on an instance (it's just a function) - the first argument will be its class.
Because it's just a function, it can only be declared once in any given scope (i.e. class definition). If follows therefore, as a surprise to a Rubyist, that you can't have a class method and an instance method with the same name.
Consider this:
class Foo():
def foo(x):
print(x)
You can call foo on an instance
Foo().foo()
<__main__.Foo instance at 0x7f4dd3e3bc20>
But not on a class:
Foo.foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method foo() must be called with Foo instance as first argument (got nothing instead)
Now add #classmethod:
class Foo():
#classmethod
def foo(x):
print(x)
Calling on an instance now passes its class:
Foo().foo()
__main__.Foo
as does calling on a class:
Foo.foo()
__main__.Foo
It's only convention that dictates that we use self for that first argument on an instance method and cls on a class method. I used neither here to illustrate that it's just an argument. In Ruby, self is a keyword.
Contrast with Ruby:
class Foo
def foo()
puts "instance method #{self}"
end
def self.foo()
puts "class method #{self}"
end
end
Foo.foo()
class method Foo
Foo.new.foo()
instance method #<Foo:0x000000020fe018>
The Python class method is just a decorated function and you can use the same techniques to create your own decorators. A decorated method wraps the real method (in the case of #classmethod it passes the additional class argument). The underlying method is still there, hidden but still accessible.
footnote: I wrote this after a name clash between a class and instance method piqued my curiosity. I am far from a Python expert and would like comments if any of this is wrong.
This is an interesting topic. My take on it is that python classmethod operates like a singleton rather than a factory (which returns a produced an instance of a class). The reason it is a singleton is that there is a common object that is produced (the dictionary) but only once for the class but shared by all instances.
To illustrate this here is an example. Note that all instances have a reference to the single dictionary. This is not Factory pattern as I understand it. This is probably very unique to python.
class M():
#classmethod
def m(cls, arg):
print "arg was", getattr(cls, "arg" , None),
cls.arg = arg
print "arg is" , cls.arg
M.m(1) # prints arg was None arg is 1
M.m(2) # prints arg was 1 arg is 2
m1 = M()
m2 = M()
m1.m(3) # prints arg was 2 arg is 3
m2.m(4) # prints arg was 3 arg is 4 << this breaks the factory pattern theory.
M.m(5) # prints arg was 4 arg is 5
I was asking myself the same question few times. And even though the guys here tried hard to explain it, IMHO the best answer (and simplest) answer I have found is the description of the Class method in the Python Documentation.
There is also reference to the Static method. And in case someone already know instance methods (which I assume), this answer might be the final piece to put it all together...
Further and deeper elaboration on this topic can be found also in the documentation:
The standard type hierarchy (scroll down to Instance methods section)
#classmethod can be useful for easily instantiating objects of that class from outside resources. Consider the following:
import settings
class SomeClass:
#classmethod
def from_settings(cls):
return cls(settings=settings)
def __init__(self, settings=None):
if settings is not None:
self.x = settings['x']
self.y = settings['y']
Then in another file:
from some_package import SomeClass
inst = SomeClass.from_settings()
Accessing inst.x will give the same value as settings['x'].
A class defines a set of instances, of course. And the methods of a class work on the individual instances. The class methods (and variables) a place to hang other information that is related to the set of instances over all.
For example if your class defines a the set of students you might want class variables or methods which define things like the set of grade the students can be members of.
You can also use class methods to define tools for working on the entire set. For example Student.all_of_em() might return all the known students. Obviously if your set of instances have more structure than just a set you can provide class methods to know about that structure. Students.all_of_em(grade='juniors')
Techniques like this tend to lead to storing members of the set of instances into data structures that are rooted in class variables. You need to take care to avoid frustrating the garbage collection then.
Classes and Objects concepts are very useful in organizing things. It's true that all the operations that can be done by a method can also be done using a static function.
Just think of a scenario, to build a Students Databases System to maintain student details.
You need to have details about students, teachers and staff. You need to build functions to calculate fees, salary, marks, etc. Fees and marks are only applicable for students, salary is only applicable for staff and teachers. So if you create separate classes for every type of people, the code will be organized.

Categories