Is it instance? or a class? python paradox - python

def F(thing):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco():
return "Deco:" + self.inst.who()
return C
class worker(object):
def who(self):
return "I am a worker"
worker = F(worker)
w = worker()
print(w.deco())
Question: what prototype does the function F return(what is "C" when F() return C)? Is it a instance(object)? or a class?
It looked like what F(worker) return is a class, instead of an instance.
The reason is Because if it is an instance, then worker = F(worker) is also an instance, yes?
Then when calling for the instance: w = worker(), we need a __call__ function in the decorator, C, otherwise we cannot call it. But actually we don't have __call__ here, so it looked like it is a class.
If you admit it , then please look at the following:
class F(object):
def __init__(self, anything):
self.anything = anything
def __call__(self):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco():
return "Deco:" + self.inst.who()
return C(self.anything())
class worker(object):
def who(self):
return "I am a worker"
worker = F(worker)
w = worker()
print(w.deco())
Now, tell me what is the prototype of worker = F(worker) now? In principle, no matter what F() is, it should not affect the prototype of worker, right?
Then "worker"(not worker()) here should be a class, as usual(as we deduced in the first case). But in this case, it is not! because when we call worker = F(worker), for F is a class, then it will initiating an instance by calling __init__! Then now worker is the instance!

Your code doesn't even work as is. If you fix your code to actually be valid python, then for your first question, F returns a class, C which gets instantiated when you say w = worker()
def F(thing):
class C(object):
def __init__(self):
self.inst = thing()
def deco(self):
return "Deco:" + self.inst.who()
return C
class Worker(object):
def who(self):
return "I am a worker"
worker = F(Worker)
print(worker)
w = worker()
print(w)
print(w.deco())
You would get
<class '__main__.C'>
<__main__.C object at 0x2471e4>
Deco:I am a worker
For the second question, F is creating an instance of itself and when you call that instance, it returns an instance of class C.
class F(object):
def __init__(self, anything):
self.anything = anything
def __call__(self):
class C(object):
def __init__(self, thing):
self.inst = thing()
def deco(self):
return "Deco:" + self.inst.who()
return C(self.anything)
class Worker(object):
def who(self):
return "I am a worker too"
worker = F(Worker)
print(worker)
w = worker()
print(w)
print(w.deco())
and you would get
<__main__.F object at 0x243444>
<__main__.C object at 0x243b0c>
Deco:I am a worker too

Related

Most pythonic way to super parent class and pass class variables

I have a parent class and a child class. The parent class needs some predefined class variables to run call(). The objects are not defined in the child class.
Question: What is the most pythonic way to pass the variables when calling super() without changing the parent class.
Example:
class Parent:
def __init__(self):
self.my_var = 0
def call(self):
return self.my_var + 1
class Child(Parent):
def __init__(self):
self.different_var = 1
def call(self):
my_var = 0
super().__call__() # What is the most pythonic way of performing this line
I know I could just make my_var in the child class a class object and it would work, but there must be a better. If not that would be an acceptable answer as well.
Your version is just a mixin. You have to __init__ the super.
class Parent:
def __init__(self):
self.my_var = 0
def call(self):
return self.my_var + 1
class Child(Parent):
def __init__(self):
super().__init__() #init super
self.different_var = 1
def call(self):
self.my_var = 50
return super().call() #return call() from super
c = Child()
print(c.call()) #51

Python proxy class

I'm trying to create a Proxy class to another class. I want this class to be passed into the proxy in its constructor and then for the proxy to dynamically create all the same methods of this class on itself.
This is what I hvae so far which is not working:
import inspect
from optparse import OptionParser
class MyClass:
def func1(self):
print 'MyClass.func1'
def func2(self):
print 'MyClass.func1'
class ProxyClass:
def __init__(self):
myClass = MyClass()
members = inspect.getmembers(MyClass, predicate=inspect.ismethod)
for member in members:
funcName = member[0]
def fn(self):
print 'ProxyClass.' + funcName
return myClass[funcName]()
self.__dict__[funcName] = fn
proxyClass = ProxyClass()
proxyClass.func1()
proxyClass.func2()
I think it is the line self.__dict__[funcName] = fn that needs to be changed but am not sure what to?
I'm new to Python so if there is a completely different Pythonic way of doing this I would be happy to hear about that too.
I would not explicitly copy the methods of the wrapped class. You can use the magic method __getattr__ to control what happens when you call something on the proxy object, including decorating it as you like; __getattr__ has to return a callable object, so you can make that callable do whatever you need to (in addition to calling the original method).
I have included an example below.
class A:
def foo(self): return 42
def bar(self, n): return n + 5
def baz(self, m, n): return m ** n
class Proxy:
def __init__(self, proxied_object):
self.__proxied = proxied_object
def __getattr__(self, attr):
def wrapped_method(*args, **kwargs):
print("The method {} is executing.".format(attr))
result = getattr(self.__proxied, attr)(*args, **kwargs)
print("The result was {}.".format(result))
return result
return wrapped_method
proxy = Proxy(A())
proxy.foo()
proxy.bar(10)
proxy.baz(2, 10)

How to call child constructor from parent?

In inheritance, most of the time we want to create child classes that inherit from the parent, and in the process of instantiation they have to call the parent constructor. In python we use super for this, and that's great.
I want to do somewhat the opposite: I have a parent class which is a template for a number of child classes. Then I want the child classes to each have a function that allows an instance to clone itself:
class Parent(object):
def __init__(self, ctype, a):
print('This is the parent constructor')
self._ctype = ctype
self._a = a
#property
def a(self):
return self._a
#property
def ctype(self):
return self._ctype
class ChildOne(Parent):
def __init__(self, a):
super(ChildOne, self).__init__('one', a)
print('This is the child One constructor')
self.one = 1
def clone(self):
return ChildOne(self._a)
class ChildTwo(Parent):
def __init__(self, a):
super(ChildTwo, self).__init__('two', a)
print('This is the child Two constructor')
self.two = 2
def clone(self):
return ChildTwo(self._a)
Now, if I create an instance of one of the children, I can clone it:
>>> k = ChildOne(42)
>>> k.ctype
'one'
>>> l = k.clone()
>>> l.a
42
>>> l is k
False
The problem is, the clone method is repeated- and nearly identical- in both sub-classes, except I need to specify explicitly which constructor to call. Is it possible to design a clone method that I define in the parent class, that correctly inherits to the children?
This can be done with:
Code:
class Parent(object):
def clone(self):
return type(self)(self._a)
Test Code:
class Parent(object):
def __init__(self, ctype, a):
print('This is the parent constructor')
self._ctype = ctype
self._a = a
#property
def a(self):
return self._a
#property
def ctype(self):
return self._ctype
def clone(self):
return type(self)(self._a)
class ChildOne(Parent):
def __init__(self, a):
super(ChildOne, self).__init__('one', a)
print('This is the child One constructor')
self.one = 1
class ChildTwo(Parent):
def __init__(self, a):
super(ChildTwo, self).__init__('two', a)
print('This is the child Two constructor')
self.two = 2
k = ChildOne(42)
print(k.ctype)
l = k.clone()
print(l.a)
print(type(l))
Results:
This is the parent constructor
This is the child One constructor
one
This is the parent constructor
This is the child One constructor
42
<class '__main__.ChildOne'>

How to access property cross class and cross file in Python?

Now I need a property which in another class to do something in one class.
just like:
a.py
class A:
def __init__(self, io_loop): # the same io_loop instance
self.access = None
self.w_id = None
self.io_loop = io_loop
#gen.coroutine
def setup(self):
# `async_client` has the `get`, 'post', 'put', 'delete' methods
self.access = yield async_client()
#gen.coroutine
def do_something(self):
self.w_id = self.access.get('w_id')
...
def run(self):
self.io_loop.run_sync(self.setup)
self.io_loop.spawn_callback(self.do_something)
self.io_loop.start()
if __name__ == '__main__':
a = A()
a.run()
-
b.py
class B:
def __init__(self, io_loop):
self.w_id = None
self.io_loop = io_loop # the same io_loop instance
# How can i get the w_id from `class A`
def run(self):
...
if __name__ == '__main__':
b = B()
b.run()
Notice:
when zone_id of class B is not None, class B can do next. that's means, if class A zone_id is None, class B will waiting for it.
And the class A and class B only could initialize one instance.
the class A and class B in differents files.
You can't access that variable until you create an instance that initializes. Otherwise, w_id doesn't exist in A.
If you want to give w_id an arbitrary value for access from other classes, put it as a class variable, means you write directly w_id = 'some value' inside class A with the same indentation as the defs:
class A:
w_id = something
def __init__(self):
...
class B:
def __init__(self):
self.w_id = A.w_id
Otherwise, you need an instance of A, like that:
class B:
def __init__(self):
a = A()
a.do_something()
self.w_id = a.w_id
The only other option is to create the same functions inside B:
class B:
...
#gen.coroutine
def setup(self):
# `async_client` has the `get`, 'post', 'put', 'delete' methods
self.access = yield async_client()
#gen.coroutine
def do_something(self):
self.w_id = self.access.get('w_id')
...
As you mentioned that io_loop is the same instance in all of the classes, it might occur that you need to create a copy of it if your functions uses it. You can't change a variable and expect it to stay unchanged.

Accidentally calling an ovverriden method from base class's __init__

This program seems to do everything by the book, yet this issue cropped up: while a base class was being init'ed a member method was called that is overriden in the derived class and assumes that the derived class has been constructed.
Is there some best practice to protect against this?
#!/usr/bin/env python3
class A:
def __init__(self):
self.ax = 1
print(self)
def __repr__(self):
return "{} ax: {}".format(self.__class__.__name__, self.ax)
class B(A):
def __init__(self):
super().__init__()
self.bx = 10
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
if __name__ == "__main__":
B()
And here's the error:
AttributeError: 'B' object has no attribute 'bx'
Generally, unless you really know what you are doing, you want to call the superclass initialization after everything your class needs to do is done. Same with this example, repr is trying to print self.bx before you initialize it. If you do
class B(A):
def __init__(self):
self.bx = 10
super().__init__()
def __repr__(self):
return super().__repr__() + " bx: {}".format(self.bx)
it works as expected
Edited:
Instead of doing computation on __init__, one idea may be to do that in a factory function/classmethod.
Example instead of doing:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
self.initialize()
def initialize(self):
# do some things
Do:
class A:
def __init__(self, a, b):
self.a = a
self.b = b
#classmethod
def from_a_b(cls, a, b):
instance = cls(a, b)
instance.initialize()
return instance

Categories

Resources