As we can create multiple variables in a single line, such as:
x, y, z = 1, 2, 3
print(x)
and the output would be 1,
I wonder if there is something similar to create multiple empty classes, so something like this, which I know is wrong, but just to let you have an idea of what I mean:
class X, Y, Z:
pass
Thank you very much!
No, there is no special syntax to use a class definition this way. You could use the type constructor, something like:
>>> A, B, C = type('A', (object,), {}), type('B', (object,), {}), type('C', (object,), {})
>>> A, B, C
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>)
>>>
>>> A()
<__main__.A object at 0x10354d780>
>>> B()
<__main__.B object at 0x1038b1ef0>
>>> C()
<__main__.C object at 0x10354d780>
But I think that's hardly elegant, and it's unlikely you'll be able to keep the single line to a sane length. Just stick to the full class definitions.
Related
Im trying to compare types of two objects by using isinstance(obj1, type(obj2)).
However, im not really sure how type infers the typing of an object - or whether theres a chance that the type returned is of an ancestor class.
Given three classes A, B, C. Class B is subclass of A and class C is subclass of B.
class A:
pass
class B(A):
pass
class C(B):
pass
Using type on an object is the same thing as calling obj.__class__. This returns the class to which an instance belongs.
isinstance however also checks for subclasses. So your call isinstance(obj1, type(obj2)) depends on if the two objects are related.
>>> a = A()
>>> b = B()
>>> c = C()
>>> type(c) == type(b)
False
>>> isinstance(c, type(b))
True
Instance c is of type <class '__main__.C'> and b is of type <class '__main__.B'>. So the comparison using type evaluates to False.
A more elaborate example of your approach and using the class directly:
>>> isinstance(c, type(b)) # as C is subclass of B
True
>>> isinstance(c, B) # using the class directly
True
>>> isinstance(b, type(c)) # as b is of parent class B
False
>>> isinstance(b, C) # C is subclass of B, thus b is not an instance of C
False
>>> isinstance(c, type(a)) # C is subclass of B which is subclass of A
True
In python, if class C inherits from two other classes C(A,B), and A and B have methods with identical names but different return values, which value will that method return on C?
"Inherits two methods" isn't quite accurate. What happens is that C has a method resolution order (MRO), which is the list [C, A, B, object]. If you attempt to access a method that C does not define or override, the MRO determines which class will be checked next. If the desired method is defined in A, it shadows a method with the same name in B.
>>> class A:
... def foo(self):
... print("In A.foo")
...
>>> class B:
... def foo(self):
... print("In B.foo")
...
>>> class C(A, B):
... pass
...
>>> C.mro()
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
>>> C().foo()
In A.foo
MRO order will be followed now, if you inherit A and B in C, then preference order goes from left to right, so, A will be prefered and method of A will be called instead of B
Consider the following case:
>>> "a".capitalize.__call__
<method-wrapper '__call__' of builtin_function_or_method object at 0x1022e70d8>
>>> "a".capitalize.__call__.__call__
<method-wrapper '__call__' of method-wrapper object at 0x1022e2b70>
>>> id("a".capitalize.__call__)
4331547448
>>> id("a".capitalize.__call__.__call__)
4331547504
>>> id("a".capitalize.__call__) == id("a".capitalize.__call__.__call__)
False
How can I establish at runtime that the __call__ refers to the same base symbol in both cases ?
Edit:
It is possible that expecting something like this to exist for __call__ in the first place is unreasonable because __call__ might not have a base symbol that is not bound to any object - in which case what is the best way to detect that other than keeping a list of special names (how can such a list be built authoritatively ?) ?
Won't work for builtin_function_or_method as they have no __func__.
If you're only working with your classes you can compare __func__:
>>> class Foo:
... def bar(self):
... pass
...
>>>
>>> a = Foo()
>>> b = Foo()
>>> a.bar.__func__
<function Foo.bar at 0x7f6f103e5ae8>
>>> a.bar.__func__ is b.bar.__func__
True
But I'd say it's better to do it the other way around: instead of trying to get the function from the instance, get up to the type first:
type(a).bar is type(a).bar
Which should work even for bltns:
>>> type("").capitalize is type("a").capitalize
True
And for hierarchies:
>>> class A:
... def foo(self):...
...
>>> class B(A):...
...
>>> a = A()
>>> b = B()
>>> type(a).foo is type(b).foo
True
Code:
import types
class C(object):
pass
c = C()
print(isinstance(c, types.InstanceType))
Output:
False
What correct way to check if object is instance of user-defined class for new-style classes?
UPD:
I want put additional emphasize on if checking if type of object is user-defined. According to docs:
types.InstanceType
The type of instances of user-defined classes.
UPD2:
Alright - not "correct" ways are OK too.
UPD3:
Also noticed that there is no type for set in module types
You can combine the x.__class__ check with the presence (or not) of either '__dict__' in dir(x) or hasattr(x, '__slots__'), as a hacky way to distinguish between both new/old-style class and user/builtin object.
Actually, this exact same suggestions appears in https://stackoverflow.com/a/2654806/1832154
def is_instance_userdefined_and_newclass(inst):
cls = inst.__class__
if hasattr(cls, '__class__'):
return ('__dict__' in dir(cls) or hasattr(cls, '__slots__'))
return False
>>> class A: pass
...
>>> class B(object): pass
...
>>> a = A()
>>> b = B()
>>> is_instance_userdefined_and_newclass(1)
False
>>> is_instance_userdefined_and_newclass(a)
False
>>> is_instance_userdefined_and_newclass(b)
True
I'm not sure about the "correct" way, but one easy way to test it is that instances of old style classes have the type 'instance' instead of their actual class.
So type(x) is x.__class__ or type(x) is not types.InstanceType should both work.
>>> class Old:
... pass
...
>>> class New(object):
... pass
...
>>> x = Old()
>>> y = New()
>>> type(x) is x.__class__
False
>>> type(y) is y.__class__
True
>>> type(x) is types.InstanceType
True
>>> type(y) is types.InstanceType
False
This tells us True if it is.
if issubclass(checkthis, (object)) and 'a' not in vars(__builtins__):print"YES!"
The second argument is a tuple of the classes to be checked.
This is easy to understand and i'm sure it works.
[edit (object) to(object,) thanks Duncan!]
Probably I can go with elimination method - not checking if object is instance of user-defined class explicitly - isinstance(object, RightTypeAliasForThisCase), but checking if object not one of 'basic' types.
>>> import sys
>>> sys.version_info
(2, 4, 4, 'final', 0)
>>> class C:
... pass
...
>>> issubclass(C, C)
True
>>> issubclass(C, object)
False
>>> class T(object):
... pass
...
>>> issubclass(T, T)
True
>>> issubclass(T, object)
True
>>>
Question 1> Why C is a subclass of C?
Question 2> what is the base class of C?
Thank you
// Update for Chris Morgan (At least for me, the following manual doesn't help at all)
>>> help(issubclass)
Help on built-in function issubclass in module __builtin__:
issubclass(...)
issubclass(C, B) -> bool
Return whether class C is a subclass (i.e., a derived class) of class B.
When using a tuple as the second argument issubclass(X, (A, B, ...)),
is a shortcut for issubclass(X, A) or issubclass(X, B) or ... (etc.).
Take a look at issubclass(class, classinfo) documentation
Return true if class is a subclass (direct, indirect or virtual) of
classinfo. A class is considered a subclass of itself. classinfo may
be a tuple of class objects, in which case every entry in classinfo
will be checked. In any other case, a TypeError exception is raised.
and to check base class of C use inspect.getmro(cls) function.
Return a tuple of class cls’s base classes, including cls, in method
resolution order.
>>> class C(object):
... pass
...
>>> inspect.getmro(C)
(<class '__main__.C'>, <type 'object'>)
>>>
http://docs.python.org/library/functions.html#issubclass From that link, "A class is considered a subclass of itself."
To answer your second question, C is an "old style" class so it isn't a subclass of object. Include object as the superclass if you want a new style class. See http://www.python.org/doc/newstyle/ for more info.
http://docs.python.org/library/functions.html#issubclass
A class is considered a subclass of itself.
C has no base class
print C.__bases__
()