Refer to parent's class method without parent's class name - python

I hope you are doing great. This questions is really about getting rid of the reference to base class.
Basically I want to collect all methods of a child class methods at the class level instead of the instance level, using a parent classmethod. However, I was told that the base class name is really long.
The first piece works but is really annoying because of the long name. Even in the clean version I have to do A.eat everytime.
I promise people won't define another method "eat" in any child like B. Can I actually get rid of the base class reference so that I can use #eat?
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
class B(IDontWantToDoThisButNameHasToBeThisLong):
#IDontWantToDoThisButNameHasToBeThisLong.eat
def apple( self, x ):
print x
IDontWantToDoThisButNameHasToBeThisLong.eat( lambda x: x+1 )
x = B()
IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)
print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)
Clean version:
class A(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
class B(A):
#A.eat
def apple( self, x ):
print x
A.eat( lambda x: x+1 )
x = B()
A.a[0](x, 1)
print A.a[1](1)
Sincerely,

The class IDontWantToDoThisButNameHasToBeThisLong is really just an object. In python, most thingsa are an object, so we can assign just about anything to a variable, including a class.
What you could do here is something like the following
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
A = IDontWantToDoThisButNameHasToBeThisLong
class B(A):
#A.eat
def apple( self, x ):
print x
A.eat( lambda x: x+1 )
x = B()
IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)
A.a[0](x, 1)
print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)

There's no perfect solution for what you want to do, but there are a few different approaches that might be good enough.
To start with the simplest, you could give your long class a shorter name before using class method in the child classes:
class IDontWantToDoThisButNameHasToBeThisLong(object):
...
A = IDontWantToDoThisButNameHasToBeThisLong
# later code can use A.whatever()
Another option would be to move the decorator out of the class with the long name, so that your later code would refer to it directly as a global, rather than a class method. This would require it to be slightly redesigned (which might break things if you ever intend for there to be multiple different a lists that are accessed through the same decorator called via different classes):
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
def eat(func):
IDontWantToDoThisButNameHasToBeThisLong.a.append(func) # only need to use the name once
return func # I suspect you want this too (a decorator should return a callable)
# later code can use #eat as a decorator, without referring to the long class name
A hybrid of those two approaches might be to leave the existing class method definition intact, but to create another global name for the bound method that's easier to access:
eat = IDontWantToDoThisButNameHasToBeThisLong.eat
A final possible approach would be to use fancier programming with metaclasses, or (if you're using Python 3.6) __init_subclass__ or similar, to achieve the goal you have in mind without needing to use a class method as a decorator. I'm not going to include code for that, since the best way to do this probably depends on more details of your design than what you've show in your example.

Related

Python - inheritance and method overriding

I have two classes, one inheriting from the other. Let's call them Parent and Child.
Both of the objects created from those classes should use function funA, which looks like below
funA():
X = another_function()
Y = # some value
X.append(Y)
# do other computations
For both classes, function funA looks almost the same, except function another_function(), which computes in a different way the list X for the Parent and differently for the Child. Of course, I know that I can override function funA in the Child class, but since this function is very long and does several operations, copy-pasting it would be a little bit a waste. On the other hand - I have to distinguish that the Parent class should use one version of another_function() and the Child class should use the second version of another_function(). Is is maybe possible to point which version of another_function (let's call them another_function_v1 and another_function_v2) should be used by each class or the only solution if to override the whole function funA?
Your post is not quite clear but I assume funA is a method of Parent. If yes, just add some another_method method calling the right function:
class Parent(object):
def another_method(self):
return another_function_v1()
def funA(self):
X = self.another_method()
Y = # some value
X.append(Y)
# do other computations
class Child(Parent):
def another_method(self):
return another_method_v2()
nb if funA is a classmethod you will want to make another_method a classmethod too...
I don't know where your another_functions come. I suppose they are normal functions, which can be imported and used
class Parent(object):
another_function = another_function_v1
def funA(self):
X = self.another_function()
Y = # some value
X.append(Y)
# do other computations
class Child(Parent):
another_function = another_function_v2

Accessing instance variable from other instance in python

I am trying to find the best way of accessing an instance variable from another instance. So far I've been able to pass that variable as an argument and save it in the new instance. But I am wondering if there is some sort of "Global" variable that will work best. Specially if the classes are from different modules.
Here is my example:
class A(object):
def __init__(self):
self.globalObject = "Global Object"
self.listB = self.generateBList()
def generateBList(self):
return [B(self.globalObject, i) for i in range(10)]
class B(object):
def __init__(self, globalObject, index):
self.index = index
self.globalObject = globalObject
def splitGlobalObject(self):
return self.globalObject.split(" ")
a = A()
firstB = a.listB[0]
print firstB.splitGlobalObject()
Here when I generateBList() I need to pass always that globalObject as an argument B(self.globalObject, i), and then this object gets saved into B.globalObject, butif i had many classes that needed to access that global object im not sure if passing it always as an argument would be the best option. What would be the best way of accessing it without having to pass it always as an argument when you create instances?
I hope I explained my way properly.
Your example seems unnecessarily complicated, so I'll try to illustrate one way I've used before that I think may do what you want. If you think of creating a "world" that is the stage for what you want to happen, you can have each class instance inside the world, know the world. Like this:
class Thing(object):
def __init__self(self, world, name):
self.world = world
self.name = name
class Word(object):
def __init__(self):
self.everyone = [Thing(self, i) for i in range(10)]
if __name__ == '__main__':
world = World()
In this example, the World class instance carries around an attribute called everyone that is a list of ten Thing objects. More importantly for your example, each instance of Thing now carries around a pointer called self.world that points to the world class. So all Things can access all other Things via self.world.everyone, as well as anything else in the world. I also passed i into each Things init so they have a unique name in the form of an integer between 0 and 9, but that may be extra for what you need.
From here there's basically nothing that your instances can't do to each other via methods, and all without using lots of globals.
Edit: I should add that being from different modules will make no difference here, just import as many as you want and create instances of them that pass knowledge of the World instance into them. Or obviously tailor the structure to your needs while using the same idea.
It's possible to use global variables in python.
class A(object):
def __init__(self):
global globalObject
globalObject = "Global Object"
self.listB = self.generateBList()
def generateBList(self):
return [B(i) for i in range(10)]
class B(object):
def __init__(self, index):
self.index = index
def splitGlobalObject(self):
return globalObject.split(" ")
Usually you want to avoid globals. Visit http://www.python-kurs.eu/python3_global_lokal.php for more examples.

Nested Python class needs to access variable in enclosing class

I've seen a few "solutions" to this, but the solution every time seems to be "Don't use nested classes, define the classes outside and then use them normally". I don't like that answer, because it ignores the primary reason I chose nested classes, which is, to have a pool of constants (associated with the base class) accessible to all sub-class instances which are created.
Here is example code:
class ParentClass:
constant_pool = []
children = []
def __init__(self, stream):
self.constant_pool = ConstantPool(stream)
child_count = stream.read_ui16()
for i in range(0, child_count):
children.append(ChildClass(stream))
class ChildClass:
name = None
def __init__(self, stream):
idx = stream.read_ui16()
self.name = constant_pool[idx]
All classes are passed a single param, which is a custom bitstream class. My intention is to have a solution that does not require me to read the idx value for ChildClass while still in the ParentClass. All child-class stream reading should be done in the child class.
This example is over simplified. The constant pool is not the only variable i need available to all subclasses. The idx variable is not the only thing read from the stream reader.
Is this even possible in python? Is there no way to access the parent's information?
Despite my "bit patronizing" comment (fair play to call it that!), there are actually ways to achieve what you want: a different avenue of inheritance. A couple:
Write a decorator that introspects a class just after it's declared, finds inner classes, and copies attributes from the outer class into them.
Do the same thing with a metaclass.
Here's the decorator approach, since it's the most straightforward:
def matryoshka(cls):
# get types of classes
class classtypes:
pass
classtypes = (type, type(classtypes))
# get names of all public names in outer class
directory = [n for n in dir(cls) if not n.startswith("_")]
# get names of all non-callable attributes of outer class
attributes = [n for n in directory if not callable(getattr(cls, n))]
# get names of all inner classes
innerclasses = [n for n in directory if isinstance(getattr(cls, n), classtypes)]
# copy attributes from outer to inner classes (don't overwrite)
for c in innerclasses:
c = getattr(cls, c)
for a in attributes:
if not hasattr(c, a):
setattr(c, a, getattr(cls, a))
return cls
Here is a simple example of its use:
#matryoshka
class outer(object):
answer = 42
class inner(object):
def __call__(self):
print self.answer
outer.inner()() # 42
However, I can't help but think some of the ideas suggested in other answers would serve you better.
You don't need two classes here. Here's your example code written in a more concise fashion.
class ChildClass:
def __init__(self, stream):
idx = stream.read_ui16()
self.name = self.constant_pool[idx]
def makeChildren(stream):
ChildClass.constant_pool = ConstantPool(stream)
return [ChildClass(stream) for i in range(stream.read_ui16())]
Welcome to Python. Classes are mutable at runtime. Enjoy.
You can access the parent class through its name:
class ChildClass:
name = None
def __init__(self, stream):
idx = stream.read_ui16()
self.name = ParentClass.constant_pool[idx]
Then again, I'm not sure I understand what you are trying to achieve.
Another alternative design to consider:
When you find yourself trying to use classes as namespaces, it might make more sense to put the inner classes into a module of their own and make what were the attributes of the outer class global variables. In other words, if you never intend to instantiate your ParentClass, then it's just serving as a glorified module.
Global variables get a bad rap in most programming languages, but they are not truly global in Python, and are nicely encapsulated to the module.
Well, the following works (further simplified from your example). Note that you don't have to "declare" member variables at class level like C++/C#/Java etc, just set them on self within __init__:
class ParentClass:
def __init__(self):
self.constant_pool = ["test"]
self.ChildClass.constant_pool = self.constant_pool
self.children = [self.ChildClass()]
class ChildClass:
def __init__(self):
self.name = self.constant_pool[0]
print "child name is", self.name
p = ParentClass() # Prints "child name is test"
Note that you could still do the same sort of thing without the child classes being nested.
Your question uses the word subclass, so I'm keying from that to interpret your question. As with the others who have answered, I am not certain I understand what you are looking for.
class ParentClass(object):
constant_pool = [c1, c2, c3]
def __init__(self):
# anything not included in your question
class ChildClass(ParentClass):
def __init__(self, stream):
ParentClass.__init__(self)
self.name = ParentClass.constant_pool[stream.read_ui16()]
stream = get_new_stream()
children = []
for count in range(stream.read_ui16()):
children.append(ChildClass(stream))
This code uses inheritance to derive ChildClass from ParentClass (and all methods, etc). The constant_pool is an attribute of ParentClass itself, though it is OK to treat as an attribute of any instance of ParentClass or ChildClass (saying self.constant_pool within ChildClass.__init__ would be equivalent to the above but, in my view, misleading).
Nesting the class definitions is not necessary. Nesting the definition of ChildClass within ParentClass just means that ChildClass is an attribute of ParentClass, nothing more. It does not make instances of ChildClass inherit anything from ParentClass.

Compact Class DSL in python

I want to have compact class based python DSLs in the following form:
class MyClass(Static):
z = 3
def _init_(cls, x=0):
cls._x = x
def set_x(cls, x):
cls._x = x
def print_x_plus_z(cls):
print cls._x + cls.z
#property
def x(cls):
return cls._x
class MyOtherClass(MyClass):
z = 6
def _init_(cls):
MyClass._init_(cls, x=3)
I don't want to write MyClass() and MyOtherClass() afterwards. Just want to get this working with only class definitions.
MyClass.print_x_plus_z()
c = MyOtherClass
c.z = 5
c.print_x_plus_z()
assert MyOtherClass.z == 5, "instances don't share the same values!"
I used metaclasses and managed to get _init_, print_x and subclassing working properly, but properties don't work.
Could anyone suggest better alternative?
I'm using Python 2.4+
To give a class (as opposed to its instances) a property, you need to have that property object as an attribute of the class's metaclass (so you'll probably need to make a custom metaclass to avoid inflicting that property upon other classes with the same metaclass). Similarly for special methods such as __init__ -- if they're on the class they'd affect the instances (which you don't want to make) -- to have them affect the class, you need to have them on the (custom) metaclass. What are you trying to accomplish by programming everything "one metalevel up", i.e., never-instantiated class with custom metaclass rather than normal instances of a normal class? It just seems a slight amount of extra work for no returns;-).

Is there a benefit to defining a class inside another class in Python?

What I'm talking about here are nested classes. Essentially, I have two classes that I'm modeling. A DownloadManager class and a DownloadThread class. The obvious OOP concept here is composition. However, composition doesn't necessarily mean nesting, right?
I have code that looks something like this:
class DownloadThread:
def foo(self):
pass
class DownloadManager():
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadThread())
But now I'm wondering if there's a situation where nesting would be better. Something like:
class DownloadManager():
class DownloadThread:
def foo(self):
pass
def __init__(self):
dwld_threads = []
def create_new_thread():
dwld_threads.append(DownloadManager.DownloadThread())
You might want to do this when the "inner" class is a one-off, which will never be used outside the definition of the outer class. For example to use a metaclass, it's sometimes handy to do
class Foo(object):
class __metaclass__(type):
....
instead of defining a metaclass separately, if you're only using it once.
The only other time I've used nested classes like that, I used the outer class only as a namespace to group a bunch of closely related classes together:
class Group(object):
class cls1(object):
...
class cls2(object):
...
Then from another module, you can import Group and refer to these as Group.cls1, Group.cls2 etc. However one might argue that you can accomplish exactly the same (perhaps in a less confusing way) by using a module.
I don't know Python, but your question seems very general. Ignore me if it's specific to Python.
Class nesting is all about scope. If you think that one class will only make sense in the context of another one, then the former is probably a good candidate to become a nested class.
It is a common pattern make helper classes as private, nested classes.
There is another usage for nested class, when one wants to construct inherited classes whose enhanced functionalities are encapsulated in a specific nested class.
See this example:
class foo:
class bar:
... # functionalities of a specific sub-feature of foo
def __init__(self):
self.a = self.bar()
...
... # other features of foo
class foo2(foo):
class bar(foo.bar):
... # enhanced functionalities for this specific feature
def __init__(self):
foo.__init__(self)
Note that in the constructor of foo, the line self.a = self.bar() will construct a foo.bar when the object being constructed is actually a foo object, and a foo2.bar object when the object being constructed is actually a foo2 object.
If the class bar was defined outside of class foo instead, as well as its inherited version (which would be called bar2 for example), then defining the new class foo2 would be much more painful, because the constuctor of foo2 would need to have its first line replaced by self.a = bar2(), which implies re-writing the whole constructor.
You could be using a class as class generator. Like (in some off the cuff code :)
class gen(object):
class base_1(object): pass
...
class base_n(object): pass
def __init__(self, ...):
...
def mk_cls(self, ..., type):
'''makes a class based on the type passed in, the current state of
the class, and the other inputs to the method'''
I feel like when you need this functionality it will be very clear to you. If you don't need to be doing something similar than it probably isn't a good use case.
There is really no benefit to doing this, except if you are dealing with metaclasses.
the class: suite really isn't what you think it is. It is a weird scope, and it does strange things. It really doesn't even make a class! It is just a way of collecting some variables - the name of the class, the bases, a little dictionary of attributes, and a metaclass.
The name, the dictionary and the bases are all passed to the function that is the metaclass, and then it is assigned to the variable 'name' in the scope where the class: suite was.
What you can gain by messing with metaclasses, and indeed by nesting classes within your stock standard classes, is harder to read code, harder to understand code, and odd errors that are terribly difficult to understand without being intimately familiar with why the 'class' scope is entirely different to any other python scope.
A good use case for this feature is Error/Exception handling, e.g.:
class DownloadManager(object):
class DowndloadException(Exception):
pass
def download(self):
...
Now the one who is reading the code knows all the possible exceptions related to this class.
Either way, defined inside or outside of a class, would work. Here is an employee pay schedule program where the helper class EmpInit is embedded inside the class Employee:
class Employee:
def level(self, j):
return j * 5E3
def __init__(self, name, deg, yrs):
self.name = name
self.deg = deg
self.yrs = yrs
self.empInit = Employee.EmpInit(self.deg, self.level)
self.base = Employee.EmpInit(self.deg, self.level).pay
def pay(self):
if self.deg in self.base:
return self.base[self.deg]() + self.level(self.yrs)
print(f"Degree {self.deg} is not in the database {self.base.keys()}")
return 0
class EmpInit:
def __init__(self, deg, level):
self.level = level
self.j = deg
self.pay = {1: self.t1, 2: self.t2, 3: self.t3}
def t1(self): return self.level(1*self.j)
def t2(self): return self.level(2*self.j)
def t3(self): return self.level(3*self.j)
if __name__ == '__main__':
for loop in range(10):
lst = [item for item in input(f"Enter name, degree and years : ").split(' ')]
e1 = Employee(lst[0], int(lst[1]), int(lst[2]))
print(f'Employee {e1.name} with degree {e1.deg} and years {e1.yrs} is making {e1.pay()} dollars')
print("EmpInit deg {0}\nlevel {1}\npay[deg]: {2}".format(e1.empInit.j, e1.empInit.level, e1.base[e1.empInit.j]))
To define it outside, just un-indent EmpInit and change Employee.EmpInit() to simply EmpInit() as a regular "has-a" composition. However, since Employee is the controller of EmpInit and users don't instantiate or interface with it directly, it makes sense to define it inside as it is not a standalone class. Also note that the instance method level() is designed to be called in both classes here. Hence it can also be conveniently defined as a static method in Employee so that we don't need to pass it into EmpInit, instead just invoke it with Employee.level().

Categories

Resources