Access methods of member of Parent that references other module, from child - python

New to Python. Apologies for the title. Been searching for days on this problem :S
I am coming from a PHP background where I can create classes in their own files and then call those classes from anywhere as long as I have a reference to them.
For instance;
require class Z from class A.
Then have class B extend class A.
then be able to call methods on class Z from class B.
I want to have a parent class that contains methods and members that other classes can extend so that I'm not re-inventing the wheel every time I want create a class that is distinct in its own way, but also has similarities to other classes.
Maybe my understanding of how modules work in Python is wrong? Following is an example of what I'm trying to achieve. Do i need all of these classes in one module? Can someone explain the process for what I'm attempting to do?
import Z
class A():
def __init__(self):
self.varZ = Z()
self.some_value = None
def a_setter_function(self, value):
self.some_value = value
Then extending classes, for example class B through to class X;
import A
class B(A):
def some_function(self):
something = self.varZ.do_something_from_z_class()
def set_value(self, value):
self.a_setter_function(value)
Always raises;
'ClassB' object has no attribute 'varZ'
I have no issues in calling 'a_setter_function()' from class B.
Can also call methods on varZ from class A.
The only solution I can come up with is to have a method in class A (called from class B) which calls the method from class Z. ie The method I'm trying to call from Class B.
Why can't I call a method of class Z from class B via its parent class A?

Related

copy methods from one class to another (python)

so i don't know if what i am asking for is even passable or not, but never the less, i want to do is the following
class A:
def methodA(self):
pass
def methodB(self):
pass
class B:
pass
b = B()
b.methodA()
b.methodB()
but the thing is i might going to have so many number of class B objects this is why i want to assign the "A"s methods to the B class rather than to a single object of class B, i found one solution but the problem with it i have to pass the object as a parameter so for example i am going to have something like this
b.methodA(b)
b.methodB(b)
edited
so the reason why i want to do such thing is, i am making a program that will have two python interpreter whose interpreting the same python file, and i want to share objects between them by only sending/receiving the data inside the object along with the object type, so that the other interpreter will only receive the object data along with its type and make new object from class like the B class, and since both of the interpreters are interpreting the same python file, both of them will have access to the object class, so i don't really have to send the object methods, i can simply make the other interpreter copy it(if it was passable)
edited
so i will need to assign the methods and removing them in run time, and i won't be able to know what classes are the class B are going to copy methods from, until the code execution finishes
You can check Class inheritance or Polymorphism. If you have only one class that should use other's function, Inheritance is better. One will be the child of other. For example, if B will be the child of A, B will have A functions and more. read more at:
Example:
Parent
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
#Use the Person class to create an object, and then execute the printname method:
x = Person("John", "Doe")
x.printname()
Child class:
class Student(Person):
pass
Then you could use Person's functions from Student:
x = Student("Mike", "Olsen")
x.printname()
read more: https://www.w3schools.com/python/python_inheritance.asp
You can pass class A into class B, if what you are doing is to let B have functions in A.
class A():
def method1():
return 'method1'
def method2():
return 'method2'
class B(A):
pass
B.method1()
B.method2()

Access class level attribute of another class?

I can access class-level attribute of a class (B) in method of another class (A) but I cannot access that at class-level of class A.
The issue can be resolved by defining B after A but why is this so and how can I access that keeping class B after class A.
I am looking for solution without class inheritance and without creating object of class B inside __init__ of class A.
See the code here:
class A:
a=B.b # This doesn't work
def __init__(self):
print(B.b) #This works
class B:
b=[1,2,3]
Assuming you don’t need to use the attribute while defining A (e.g., for a default argument), you can just assign it later:
class A:
def __init__(self):
print(B.b)
class B:
b=[1,2,3]
A.a=B.b
or even
class A:
def __init__(self):
print(B.b)
class B:
A.a=b=[1,2,3]
if you consider the classes so closely related that an assignment to one inside the other is less surprising than one outside both.

How to refer from child class to child class of another class

I know the title of the question is very confusing. I couldn't come up with anything meaningful. Let me explain it.
I have two classes, let's call them A and B:
class A(object):
def get_instance_of_b():
return B()
class B(object):
pass
In it I have a method that refers to instance of class B.
I have 4 classes that inherit from A and another 4 classes that inherit from class B. Now what I want is to avoid rewriting get_instance_of_b() method. Class A1 (child of A) should get an instance of B1 (child of B) and so on.
What is the best way to do it? Or maybe I'm going wrong with classes structure?
To give a context to what my classes do: class A processes data and class B validates input parameters. All children of class A share some general parameters but children classes also have their own specific parameters.
You should have an explicit mapping of your A classes (your "processors") to your B classes (your "validators"), and do the lookup that way.
class A(object):
def get_validator(self):
return validators[self.__class__]()
class A1(A):
...
class B(object):
...
class B1(B):
...
validators = {A:B, A1:B1}
And use as such:
>>> a1 = A1()
>>> a1.get_validator()
<__main__.B1 object at ...>

Pythonic way to assign an instance of a subclass to a variable when a specific string is presented to the constructor of the parent class

I want to be able to create an instance of a parent class X, with a string "Q" as an extra argument.
This string is to be a name being an identifier for a subclass Q of the parent class X.
I want the instance of the parent class to become (or be replaced with) an instance of the subclass.
I am aware that this is probably a classic problem (error?). After some searching I haven't found a suitable solution though.
I came up with the following solution myself;
I added a dictionary of possible identifiers as keys for their baseclass-instances to the init-method of the parent class.
Then assigned the class-attribute of the corresponding subclass to the current instances class-attribute.
I required the argument of the init-method not to be the default value to prevent infinite looping.
Following is an example of what the code looks like in practice;
class SpecialRule:
""""""
name="Special Rule"
description="This is a Special Rule."
def __init__(self, name=None):
""""""
print "SpecialInit"
if name!=None:
SPECIAL_RULES={
"Fly" : FlyRule(),
"Skirmish" : SkirmishRule()
} #dictionary coupling names to SpecialRuleclasses
self.__class__= SPECIAL_RULES[name].__class__
def __str__(self):
""""""
return self.name
class FlyRule(SpecialRule):
""""""
name="Fly"
description="Flies."
def __init__(self):
""""""
print "FlyInit"+self.name
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
class SkirmishRule(SpecialRule):
""""""
name="Skirmish"
description="Skirmishes."
def __init__(self):
""""""
SpecialRule.__init__(self)
def addtocontainer(self, container):
"""this instance messes with the attributes of its containing class when added to some sort of list"""
test=SpecialRule("Fly")
print "evaluating resulting class"
print test.description
print test.__class__
</pre></code>
output:
>
SpecialInit
FlyInitFly
SpecialInit
evaluating resulting class
Flies.
main.FlyRule
>
Is there a more pythonic solution and are there foresee-able problems with mine?
(And am I mistaken that its a good programming practice to explicitly call the .__init__(self) of the parent class in .__init__ of the subclass?).
My solution feels a bit ... wrong ...
Quick recap so far;
Thanks for the quick answers
# Mark Tolonen's solution
I've been looking into the __new__-method, but when I try to make A, B and C in Mark Tolonen's example subclasses of Z, I get the error that class Z isn't defined yet. Also I'm not sure if instantiating class A the normal way ( with variable=A() outside of Z's scope ) is possible, unless you already have an instance of a subclass made and call the class as an attribute of an instance of a subclass of Z ... which doesn't seem very straightforward. __new__ is quite interesting so I'll fool around with it a bit more, your example is easier to grasp than what I got from the pythondocs.
# Greg Hewgill's solution
I tried the staticmethod-solution and it seems to work fine. I looked into using a seperate function as a factory before but I guessed it would get hard to manage a large program with a list of loose strands of constructor code in the main block, so I'm very happy to integrate it in the class.
I did experiment a bit seeing if I could turn the create-method into a decorated .__call__() but it got quite messy so I'll leave it at that.
I would solve this by using a function that encapsulates the choice of object:
class SpecialRule:
""""""
name="Special Rule"
description="This is a Special Rule."
#staticmethod
def create(name=None):
""""""
print "SpecialCreate"
if name!=None:
SPECIAL_RULES={
"Fly" : FlyRule,
"Skirmish" : SkirmishRule
} #dictionary coupling names to SpecialRuleclasses
return SPECIAL_RULES[name]()
else:
return SpecialRule()
I have used the #staticmethod decorator to allow you to call the create() method without already having an instance of the object. You would call this like:
SpecialRule.create("Fly")
Look up the __new__ method. It is the correct way to override how a class is created vs. initialized.
Here's a quick hack:
class Z(object):
class A(object):
def name(self):
return "I'm A!"
class B(object):
def name(self):
return "I'm B!"
class C(object):
def name(self):
return "I'm C!"
D = {'A':A,'B':B,'C':C}
def __new__(cls,t):
return cls.D[t]()

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