Python Instantiating SubClasses - python

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.)

Related

Python v2 nested subclass "global name '<ClassName>' is not defined"

First off, let me say that yes I have researched this extensively for a few days now with no luck. I have looked at numerous examples and similar situations such as this one, but so far nothing has been able to resolve me issue.
My problem is I have a Python project that has a primary class, with two nested classes (yea yea I know), one of those classes is a subclass of the first. I can not figure out why I keep getting NameError: global name 'InnerSubClass' is not defined.
I understand scoping (both classes in question are in the same scope) but nothing I try seems to resolve the issue (I want to keep the two classes nested at a minimum) despite this problem working for other people.
Here is a simple example of what I am trying to do:
class SomeClass(object):
def __init__(self):
"""lots of other working stuff"""
class MainClass(object):
def __init__(self):
self.stuff = []
self.moreStuffs = []
class InnerClass(object):
def __init__(self, thing, otherThing):
self.thing = thing
self.otherThing = otherThing
self.otherStuff = []
class InnerSubClass(InnerClass):
def __init__(self, thing, otherThing, newThing):
super(InnerSubClass).__init__(thing, otherThing)
self.newThing = newThing
"""other code that worked before the addition of 'InnerSubClass'"""
def doSomething(self):
innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
print("just more thing words %s" % innerclass.newThing)
myThing = MainClass()
myThing.doSomething()
I have tried changing super(InnerSubClass).__init__(thing, otherThing)
to
super(InnerClass.InnerSubClass).__init__(thing, otherThing)
and even
super(MainClass.InnerClass.InnerSubClass).__init__(thing, otherThing) with no success. I made "InnerSubClass" inherit straight from object InnerSubClass(object): etc, and it still doesn't work.
Granted I am far from a seasoned python developer and come from mostly other compiled OO languages, and can't seem to wrap my head around why this isn't working. If I get rid of the "InnerSubClass", everything works just fine.
It doesn't seem like python offers "private" classes and functions like other languages, which is fine but I would like to utilize the nesting to at least keep objects "lumped" together. In this case, nothing should be instantiating "InnerClass" or "InnerSubClass" except functions in "MainClass".
Please provide helpful advice and explain why it doesn't work as expected with background information on how this should be done properly. If this was as simple as it seems, it would have been figured out by now.
edit: for clarification, this is only for v2
There is no "class scope" in lookup order
When creating a new class, the code in the body is executed and the resulting names are passed to type for creation. Python lookups go from inner to outer, but you don't have a "class level", only the names you define to become attributes/methods of your new class. In fact, if you want to access class variables inside a method, you use MyClass.attr instead of simple attr.
The inheritance works because InnerSubClass(InnerClass) occurs inside the class creation. To access InnerClass after MainClass has been created, do the same as you would for class attributes: MainClass.InnerClass
Just to include an example:
class Outer:
out = 1
class Inner:
inside = 2
try:
print(out) # this is confusing
except NameError:
print("can't find out")
def f(self):
try:
print(inside) # this is clear
except NameError:
print("can't find inside")
try:
print(Inner.inside) # this is less clear
except NameError:
print("can't find Inner.inside")
Outer.Inner().f()
# can't find anything
Edit:
The above is a general view, to apply it directly to your situation, look at your inner classes the way you look at regular class attributes. You'd access these as MyClass.attr, where MyClass is defined globally. If you replace attr with InnerSubClass, you get the class (attribute lookup doesn't care about inheritance, but about where the attributes are).
A stripped-down example with nested inheriting classes:
class MainClass(object):
class Inner(object):
pass
class InnerSub(Inner):
def __init__(self):
print(super(MainClass.InnerSub)) # note you use MainClass, known globally
def f(self):
return self.InnerSub()
MainClass().f() # prints "<super ...>" and returns a MainCLass.InnerSub object
Here they do it like this
super(MainClass.InnerSubClass, self).__init__(thing, otherThing)
So that you can test it here is the full working example
class SomeClass(object):
def __init__(self):
"""lots of other working stuff"""
class MainClass(object):
def __init__(self):
self.stuff = []
self.moreStuffs = []
class InnerClass(object):
def __init__(self, thing, otherThing):
self.thing = thing
self.otherThing = otherThing
self.otherStuff = []
class InnerSubClass(InnerClass):
def __init__(self, thing, otherThing, newThing):
super(MainClass.InnerSubClass, self).__init__(thing, otherThing)
self.newThing = newThing
"""other code that worked before the addition of 'InnerSubClass'"""
def doSomething(self):
innerclass = self.InnerSubClass('thisthing', 'thatthing', 'thingthing')
print("just more thing words %s" % innerclass.newThing)
print("and I also inherit from InnerClass %s" % innerclass.otherThing)
myThing = MainClass()
myThing.doSomething()
The output is
just more thing words thingthing
and I also inherit from InnerClass thatthing
If you have reasons for not using MainClass.InnerSubClass, you can also use type(self) or self.__class__ (OK, but which one) inside __init__ to get the containing class. This works well lots of layers deep (which shouldn't happen anyway), and requires the argument passed to super to be the type of the instance (which it should be anyway) but breaks if you subclass, as seen here. The concept might be clearer to you than scoping rules:
class MainClass:
class Inner:
pass
class InnerSub(Inner):
def __init__(self):
print(super(self.__class__))
print(super(type(self)))
MainClass().InnerSub()

Python inheritance: convert from Base class to Derived class

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

Find class in which a method is defined

I want to figure out the type of the class in which a certain method is defined (in essence, the enclosing static scope of the method), from within the method itself, and without specifying it explicitly, e.g.
class SomeClass:
def do_it(self):
cls = enclosing_class() # <-- I need this.
print(cls)
class DerivedClass(SomeClass):
pass
obj = DerivedClass()
# I want this to print 'SomeClass'.
obj.do_it()
Is this possible?
If you need this in Python 3.x, please see my other answer—the closure cell __class__ is all you need.
If you need to do this in CPython 2.6-2.7, RickyA's answer is close, but it doesn't work, because it relies on the fact that this method is not overriding any other method of the same name. Try adding a Foo.do_it method in his answer, and it will print out Foo, not SomeClass
The way to solve that is to find the method whose code object is identical to the current frame's code object:
def do_it(self):
mro = inspect.getmro(self.__class__)
method_code = inspect.currentframe().f_code
method_name = method_code.co_name
for base in reversed(mro):
try:
if getattr(base, method_name).func_code is method_code:
print(base.__name__)
break
except AttributeError:
pass
(Note that the AttributeError could be raised either by base not having something named do_it, or by base having something named do_it that isn't a function, and therefore doesn't have a func_code. But we don't care which; either way, base is not the match we're looking for.)
This may work in other Python 2.6+ implementations. Python does not require frame objects to exist, and if they don't, inspect.currentframe() will return None. And I'm pretty sure it doesn't require code objects to exist either, which means func_code could be None.
Meanwhile, if you want to use this in both 2.7+ and 3.0+, change that func_code to __code__, but that will break compatibility with earlier 2.x.
If you need CPython 2.5 or earlier, you can just replace the inpsect calls with the implementation-specific CPython attributes:
def do_it(self):
mro = self.__class__.mro()
method_code = sys._getframe().f_code
method_name = method_code.co_name
for base in reversed(mro):
try:
if getattr(base, method_name).func_code is method_code:
print(base.__name__)
break
except AttributeError:
pass
Note that this use of mro() will not work on classic classes; if you really want to handle those (which you really shouldn't want to…), you'll have to write your own mro function that just walks the hierarchy old-school… or just copy it from the 2.6 inspect source.
This will only work in Python 2.x implementations that bend over backward to be CPython-compatible… but that includes at least PyPy. inspect should be more portable, but then if an implementation is going to define frame and code objects with the same attributes as CPython's so it can support all of inspect, there's not much good reason not to make them attributes and provide sys._getframe in the first place…
First, this is almost certainly a bad idea, and not the way you want to solve whatever you're trying to solve but refuse to tell us about…
That being said, there is a very easy way to do it, at least in Python 3.0+. (If you need 2.x, see my other answer.)
Notice that Python 3.x's super pretty much has to be able to do this somehow. How else could super() mean super(THISCLASS, self), where that THISCLASS is exactly what you're asking for?*
Now, there are lots of ways that super could be implemented… but PEP 3135 spells out a specification for how to implement it:
Every function will have a cell named __class__ that contains the class object that the function is defined in.
This isn't part of the Python reference docs, so some other Python 3.x implementation could do it a different way… but at least as of 3.2+, they still have to have __class__ on functions, because Creating the class object explicitly says:
This class object is the one that will be referenced by the zero-argument form of super(). __class__ is an implicit closure reference created by the compiler if any methods in a class body refer to either __class__ or super. This allows the zero argument form of super() to correctly identify the class being defined based on lexical scoping, while the class or instance that was used to make the current call is identified based on the first argument passed to the method.
(And, needless to say, this is exactly how at least CPython 3.0-3.5 and PyPy3 2.0-2.1 implement super anyway.)
In [1]: class C:
...: def f(self):
...: print(__class__)
In [2]: class D(C):
...: pass
In [3]: D().f()
<class '__main__.C'>
Of course this gets the actual class object, not the name of the class, which is apparently what you were after. But that's easy; you just need to decide whether you mean __class__.__name__ or __class__.__qualname__ (in this simple case they're identical) and print that.
* In fact, this was one of the arguments against it: that the only plausible way to do this without changing the language syntax was to add a new closure cell to every function, or to require some horrible frame hacks which may not even be doable in other implementations of Python. You can't just use compiler magic, because there's no way the compiler can tell that some arbitrary expression will evaluate to the super function at runtime…
If you can use #abarnert's method, do it.
Otherwise, you can use some hardcore introspection (for python2.7):
import inspect
from http://stackoverflow.com/a/22898743/2096752 import getMethodClass
def enclosing_class():
frame = inspect.currentframe().f_back
caller_self = frame.f_locals['self']
caller_method_name = frame.f_code.co_name
return getMethodClass(caller_self.__class__, caller_method_name)
class SomeClass:
def do_it(self):
print(enclosing_class())
class DerivedClass(SomeClass):
pass
DerivedClass().do_it() # prints 'SomeClass'
Obviously, this is likely to raise an error if:
called from a regular function / staticmethod / classmethod
the calling function has a different name for self (as aptly pointed out by #abarnert, this can be solved by using frame.f_code.co_varnames[0])
Sorry for writing yet another answer, but here's how to do what you actually want to do, rather than what you asked for:
this is about adding instrumentation to a code base to be able to generate reports of method invocation counts, for the purpose of checking certain approximate runtime invariants (e.g. "the number of times that method ClassA.x() is executed is approximately equal to the number of times that method ClassB.y() is executed in the course of a run of a complicated program).
The way to do that is to make your instrumentation function inject the information statically. After all, it has to know the class and method it's injecting code into.
I will have to instrument many classes by hand, and to prevent mistakes I want to avoid typing the class names everywhere. In essence, it's the same reason why typing super() is preferable to typing super(ClassX, self).
If your instrumentation function is "do it manually", the very first thing you want to turn it into an actual function instead of doing it manually. Since you obviously only need static injection, using a decorator, either on the class (if you want to instrument every method) or on each method (if you don't) would make this nice and readable. (Or, if you want to instrument every method of every class, you might want to define a metaclass and have your root classes use it, instead of decorating every class.)
For example, here's an easy way to instrument every method of a class:
import collections
import functools
import inspect
_calls = {}
def inject(cls):
cls._calls = collections.Counter()
_calls[cls.__name__] = cls._calls
for name, method in cls.__dict__.items():
if inspect.isfunction(method):
#functools.wraps(method)
def wrapper(*args, **kwargs):
cls._calls[name] += 1
return method(*args, **kwargs)
setattr(cls, name, wrapper)
return cls
#inject
class A(object):
def f(self):
print('A.f here')
#inject
class B(A):
def f(self):
print('B.f here')
#inject
class C(B):
pass
#inject
class D(C):
def f(self):
print('D.f here')
d = D()
d.f()
B.f(d)
print(_calls)
The output:
{'A': Counter(),
'C': Counter(),
'B': Counter({'f': 1}),
'D': Counter({'f': 1})}
Exactly what you wanted, right?
You can either do what #mgilson suggested or take another approach.
class SomeClass:
pass
class DerivedClass(SomeClass):
pass
This makes SomeClass the base class for DerivedClass.
When you normally try to get the __class__.name__ then it will refer to derived class rather than the parent.
When you call do_it(), it's really passing DerivedClass as self, which is why you are most likely getting DerivedClass being printed.
Instead, try this:
class SomeClass:
pass
class DerivedClass(SomeClass):
def do_it(self):
for base in self.__class__.__bases__:
print base.__name__
obj = DerivedClass()
obj.do_it() # Prints SomeClass
Edit:
After reading your question a few more times I think I understand what you want.
class SomeClass:
def do_it(self):
cls = self.__class__.__bases__[0].__name__
print cls
class DerivedClass(SomeClass):
pass
obj = DerivedClass()
obj.do_it() # prints SomeClass
[Edited]
A somewhat more generic solution:
import inspect
class Foo:
pass
class SomeClass(Foo):
def do_it(self):
mro = inspect.getmro(self.__class__)
method_name = inspect.currentframe().f_code.co_name
for base in reversed(mro):
if hasattr(base, method_name):
print(base.__name__)
break
class DerivedClass(SomeClass):
pass
class DerivedClass2(DerivedClass):
pass
DerivedClass().do_it()
>> 'SomeClass'
DerivedClass2().do_it()
>> 'SomeClass'
SomeClass().do_it()
>> 'SomeClass'
This fails when some other class in the stack has attribute "do_it", since this is the signal name for stop walking the mro.

python: determine if a class is nested

Suppose you have a python method that gets a type as parameter; is it possible to determine if the given type is a nested class?
E.g. in this example:
def show_type_info(t):
print t.__name__
# print outer class name (if any) ...
class SomeClass:
pass
class OuterClass:
class InnerClass:
pass
show_type_info(SomeClass)
show_type_info(OuterClass.InnerClass)
I would like the call to show_type_info(OuterClass.InnerClass) to show also that InnerClass is defined inside OuterClass.
AFAIK, given a class and no other information, you can't tell whether or not it's a nested class. However, see here for how you might use a decorator to determine this.
The problem is that a nested class is simply a normal class that's an attribute of its outer class. Other solutions that you might expect to work probably won't -- inspect.getmro, for example, only gives you base classes, not outer classes.
Also, nested classes are rarely needed. I would strongly reconsider whether that's a good approach in each particular case where you feel tempted to use one.
An inner class offers no particular special features in Python. It's only a property of the class object, no different from an integer or string property. Your OuterClass/InnerClass example can be rewritten exactly as:
class OuterClass(): pass
class InnerClass(): pass
OuterClass.InnerClass= InnerClass
InnerClass can't know whether it was declared inside another class, because that's just a plain variable binding. The magic that makes bound methods know about their owner ‘self’ doesn't apply here.
The innerclass decorator magic in the link John posted is an interesting approach but I would not use it as-is. It doesn't cache the classes it creates for each outer object, so you get a new InnerClass every time you call outerinstance.InnerClass:
>>> o= OuterClass()
>>> i= o.InnerClass()
>>> isinstance(i, o.InnerClass)
False # huh?
>>> o.InnerClass is o.InnerClass
False # oh, whoops...
Also the way it tries to replicate the Java behaviour of making outer class variables available on the inner class with getattr/setattr is very dodgy, and unnecessary really (since the more Pythonic way would be to call i.__outer__.attr explicitly).
Really a nested class is no different from any other class - it just happens to be defined somewhere else than the top-level namespace (inside another class instead). If we modify the description from "nested" to "non-top-level", then you may be able to come close enough to what you need.
eg:
import inspect
def not_toplevel(cls):
m = inspect.getmodule(cls)
return not (getattr(m, cls.__name__, []) is cls)
This will work for common cases, but it may not do what you want in situations where classes are renamed or otherwise manipulated after definition. For example:
class C: # not_toplevel(C) = False
class B: pass # not_toplevel(C.B) = True
B=C.B # not_toplevel(B) = True
D=C # D is defined at the top, but...
del C # not_toplevel(D) = True
def getclass(): # not_toplevel(getclass()) = True
class C: pass
Thank you all for your answers.
I've found this possible solution using metaclasses; I've done it more for obstination than real need, and it's done in a way that will not be applicable to python 3.
I want to share this solution anyway, so I'm posting it here.
#!/usr/bin/env python
class ScopeInfo(type): # stores scope information
__outers={} # outer classes
def __init__(cls, name, bases, dict):
super(ScopeInfo, cls).__init__(name, bases, dict)
ScopeInfo.__outers[cls] = None
for v in dict.values(): # iterate objects in the class's dictionary
for t in ScopeInfo.__outers:
if (v == t): # is the object an already registered type?
ScopeInfo.__outers[t] = cls
break;
def FullyQualifiedName(cls):
c = ScopeInfo.__outers[cls]
if c is None:
return "%s::%s" % (cls.__module__,cls.__name__)
else:
return "%s.%s" % (c.FullyQualifiedName(),cls.__name__)
__metaclass__ = ScopeInfo
class Outer:
class Inner:
class EvenMoreInner:
pass
print Outer.FullyQualifiedName()
print Outer.Inner.FullyQualifiedName()
print Outer.Inner.EvenMoreInner.FullyQualifiedName()
X = Outer.Inner
del Outer.Inner
print X.FullyQualifiedName()
If you do not set it yourself, I do not believe that there is any way to determine if the class is nested. As anyway a Python class cannot be used as a namespace (or at least not easily), I would say that the best thing to do is simply use different files.
Beginning with Python 3.3 there is a new attribute __qualname__, which provides not only the class name, but also the names of the outer classes:
In your sample this would result in:
assert SomeClass.__qualname__ == 'SomeClass'
assert OuterClass.InnerClass.__qualname__ == 'OuterClass.InnerClass'
If __qualname__ of a class does not contains a '.' it is an outer class!

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