I have a class (named "A") with some instance variables. I want to add the dir() of this variables to the dir() of instances of class A.
For example:
class A(object):
def __init__(self, x, y):
self.x = x
self.y = y
class X(object):
def f_x(self):
pass
class Y(object):
def f_y(self):
pass
x = X(); y = Y()
a = A(x,y)
I want f_x and f_y to appear in
dir(a)
Is there a better way, or a more 'correct' one, than just iterating X.dict and Y.dict and for each element, use something like:
setattr(A, str(element), element)
Thanks.
A should really be a subclass of X and Y in this case. (Just be sure to read Michele Simionato's article on super and diamond inheritence before you get too deep into it.)
class X(object):
def f_x(self):
pass
class Y(object):
def f_y(self):
pass
class A(X, Y):
def __init__(self, *args, **kwargs): # splats optional
# do what you need to here
dir(A(X(),Y())) # Ah! Lisp!
However, if you really need things to be magic, then just override __getattr__ for X to look in self.x and self.y before throwing an error. But seriously, don't do this.
Why don't you simply inherit from both classes?
class B(A, X):
pass
a = B()
dir(a)
Related
Was wondering if there was a way to set a class attribute to a specific instance from within the class definition. For example,
class Value:
def __init__(self, x):
self.x = x
# Something like
# half = Value(0.5)
>>> Value.half.x
0.5
>>> Value.half.half.x
0.5
I'm also aware I can easily set it outside the class that seems a bit more bulky and error prone, like this
class Value:
def __init__(self, x):
self.x = x
Value.half = Value(0.5)
>>> Value.half.x
0.5
>>> Value.half.half.x
0.5
No. At the time the body of the class is being evaluated, the class doesn't yet exist. A class statement is a declarative syntax for calling a metaclass:
class Value:
def __init__(self, x):
self.x = x
is roughly equivalent to
def init(self, x):
self.x = x
Value = type('Value', (object,), {'__init__': init})
Your class attribute would have to be a member of the dict passed as the third argument, which has to be fully defined before type is called.
not quite, but you can make a class method that return a new instance of your class in whatever way you want with the classmethod decorator
>>> class Value:
def __init__(self, x):
self.x=x
def __repr__(self):
return f"{type(self).__name__}({self.x})"
#classmethod
def half(cls):
return cls(0.5)
>>> Value(10)
Value(10)
>>> Value.half()
Value(0.5)
>>>
look like in py3.9 you can combine it with the property decorator to accomplish just that, see linked documentation above (but I don't have it at the moment)
Simply, you can't because the class hasn't yet existed. But you can use either metaclass or class decorator to achieve the same goal as the following shows:
#Metaclass
class Meta(type):
def __init__(cls, clsname, clsbases, clsdict):
cls.half = cls(0.5)
class Value(metaclass=Meta):
def __init__(self, x):
self.x = x
#Decorator
def decorator(cls):
cls.half = cls(0.5)
return cls
#decorator
class Value2:
def __init__(self, x):
self.x = x
print(Value.half.half.x)
print(Value.half.x)
print(Value2.half.half.x)
print(Value2.half.x)
Here is the format of my code:
class A(object):
def __init__(self, x, other):
self.other = other
self.x = x
class B(A):
def __init__(self):
# place code here
def something_else(self):
return self.x["foo"]
x is an object which I would like to call, with a subscript later on (in something_else.
I would like only x to be inherited from the parent class.
It is important that other is not inherited, so super().__init__ is not suitable.
I have attempted a workaround by creating a function within class A:
def x(self):
return self.x
so I could call super().x() in class B, but this doesn't work either.
I have attempted calling directly super.x["foo"], and this doesn't work.
How can I achieve what I want in my case?
Thanks!
Variables don't always have to be registered in the __init__ function, if you want x from class A, have a method in A:
def set_x(self, x):
self.x = x
# other stuff
you'll still be able to call set_x from class B as all functions are inherited, from there you can instantiate property x without calling __init__ from A.
As title described, I an confused as the example:
class Point(object):
def __init__(self, x=0.0, y=0.0):
self.x, self.y = x, y
#classmethod
def get_point1(cls, cor): # cor is list with x=1 and y=2
return Point(cor[0], cor[1])
#classmethod
def get_point2(cls, cor):
return cls(cor[0], cor[1])
I am confused which one(get_point1 or get_point2) should I use, and what is the difference between them?
The #classmethod decorator makes the function a class method, as opposed to instance method. To make it more robust, it is preferable to use cls rather than the actual class name where it is defined.
If you use cls, the parameter which will be passed depends on the actual class being called (for example, if you subclass Point) while using Point explicity, may cause issues if you subclass it and use the class method.
Look at this code for example
class Point(object):
def __init__(self, x=0.0, y=0.0):
self.x, self.y = x, y
#classmethod
def get_point1(cls, cor): # cor is list like [1,2] with x=1 and y=2
return Point(cor[0], cor[1])
#classmethod
def get_point2(cls, cor):
return cls(cor[0], cor[1])
class SubPoint(Point):
pass
sub1 = SubPoint.get_point1([0, 1])
sub2 = SubPoint.get_point2([2, 2])
print sub1.__class__
print sub2.__class__
<class '__main__.Point'>
<class '__main__.SubPoint'>
Is there any other difference? - well, if you need to do some logic inside your class method, which depends on class attributes, then yes it does.
NOTE on the question below. I think the 'proper' pythonic idiom is to a) create module functions, such as foo_math below, and then call their specific action against an instance within the class itself. The bottom piece of code reflects that approach.
I want to define a classmethod which takes two arguments and returns a value. I want the same method to be able to be called on a class instance with the instance value pass as one of the arguments. Can I do this without defining two distinct methods as I have done here?
class Foo(object):
__init__(x):
self.x = x
#classmethod
def foo_math(cls, x, y):
return x + y
def math(self, y):
return Foo.foo_math(self.x, y)
What I would like is:
>>> Foo.math(3, 4)
7
>>> f = Foo()
>>> f.x = 3
>>> f.math(4)
7
Short of subtyping int, here is my conclusion to this question:
def foo_math(cls, x, y):
return x + y
class Foo(object):
__init__(x):
self.x = x
def foo_math(self, y):
return foo_math(self, y)
i don't recommend doing this, but if you really want, it's this (thank you other guy on stackoverflow for first part):
class staticorinstancemethod(object):
def __init__(self, func):
self.func = func
def __get__(self, instance, owner):
return functools.partial(self.func, instance)
then, do something like
class F(object):
#staticorinstancemethod
def math(instOrNone, v1, v2=None):
return instOrNone.x + v1 if instOrNone else v1 + v2
but maybe you just want to define the __add__ and __radd__ methods...
I don't think that you can call a method from a class without defining an object of that class (class methods don't belong inside the methods of any one class), so things like Foo.math(3, 4) will return a NameError as Foo has not been defined.
With this in mind, you should modify your code to be like this (even though with the problem solved there are still some issues with the code):
# A class method would probably go here somewhere.
class Foo(object):
def __init__(self, x):
self.x = x
def foo_math(self, x, y):
return x + y
def math(self, y):
return self.foo_math(self.x, y)
Then you can do:
>>> f = Foo(3)
>>> f.math(4)
7
In Python, consider I have the following code:
class SuperClass(object):
def __init__(self, x):
self.x = x
class SubClass(SuperClass):
def __init__(self, y):
self.y = y
# how do I initialize the SuperClass __init__ here?
How do I initialize the SuperClass __init__ in the subclass? I am following the Python tutorial and it doesn't cover that. When I searched on Google, I found more than one way of doing. What is the standard way of handling this?
Python (until version 3) supports "old-style" and new-style classes. New-style classes are derived from object and are what you are using, and invoke their base class through super(), e.g.
class X(object):
def __init__(self, x):
pass
def doit(self, bar):
pass
class Y(X):
def __init__(self):
super(Y, self).__init__(123)
def doit(self, foo):
return super(Y, self).doit(foo)
Because python knows about old- and new-style classes, there are different ways to invoke a base method, which is why you've found multiple ways of doing so.
For completeness sake, old-style classes call base methods explicitly using the base class, i.e.
def doit(self, foo):
return X.doit(self, foo)
But since you shouldn't be using old-style anymore, I wouldn't care about this too much.
Python 3 only knows about new-style classes (no matter if you derive from object or not).
As of python 3.5.2, you can use:
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
https://docs.python.org/3/library/functions.html#super
Both
SuperClass.__init__(self, x)
or
super(SubClass,self).__init__( x )
will work (I prefer the 2nd one, as it adheres more to the DRY principle).
See here: http://docs.python.org/reference/datamodel.html#basic-customization
How do I initialize the base (super) class?
class SuperClass(object):
def __init__(self, x):
self.x = x
class SubClass(SuperClass):
def __init__(self, y):
self.y = y
Use a super object to ensure you get the next method (as a bound method) in the method resolution order. In Python 2, you need to pass the class name and self to super to lookup the bound __init__ method:
class SubClass(SuperClass):
def __init__(self, y):
super(SubClass, self).__init__('x')
self.y = y
In Python 3, there's a little magic that makes the arguments to super unnecessary - and as a side benefit it works a little faster:
class SubClass(SuperClass):
def __init__(self, y):
super().__init__('x')
self.y = y
Hardcoding the parent like this below prevents you from using cooperative multiple inheritance:
class SubClass(SuperClass):
def __init__(self, y):
SuperClass.__init__(self, 'x') # don't do this
self.y = y
Note that __init__ may only return None - it is intended to modify the object in-place.
Something __new__
There's another way to initialize instances - and it's the only way for subclasses of immutable types in Python. So it's required if you want to subclass str or tuple or another immutable object.
You might think it's a classmethod because it gets an implicit class argument. But it's actually a staticmethod. So you need to call __new__ with cls explicitly.
We usually return the instance from __new__, so if you do, you also need to call your base's __new__ via super as well in your base class. So if you use both methods:
class SuperClass(object):
def __new__(cls, x):
return super(SuperClass, cls).__new__(cls)
def __init__(self, x):
self.x = x
class SubClass(object):
def __new__(cls, y):
return super(SubClass, cls).__new__(cls)
def __init__(self, y):
self.y = y
super(SubClass, self).__init__('x')
Python 3 sidesteps a little of the weirdness of the super calls caused by __new__ being a static method, but you still need to pass cls to the non-bound __new__ method:
class SuperClass(object):
def __new__(cls, x):
return super().__new__(cls)
def __init__(self, x):
self.x = x
class SubClass(object):
def __new__(cls, y):
return super().__new__(cls)
def __init__(self, y):
self.y = y
super().__init__('x')