This question already has answers here:
Understanding class type '__main__.ClassName'
(2 answers)
Closed 2 years ago.
I'm creating a class and checking the arguments for __init__.
class Example:
def __init__(self, a):
for key, val in locals().items():
print(type(val))
When I create this class, (something like Example(14)) I get <class '__main__.Example'> on the first line.
I know this is 'self', but what type is it?
The __main__ prefix is present because your class is defined in your script's global scope.
>>> class A:
... pass
...
>>> a = A()
>>> type(a)
<class '__main__.A'>
>>>
The type of Example(14) is... well, Example, since that's the class of which that object is an instance.
Related
This question already has answers here:
How to access the type arguments of typing.Generic?
(5 answers)
Closed 19 days ago.
class MyClass:
prop: list[str]
MyClass.__annotations__
# {'prop': list[str]}
How do I access "str"?
As a more generic question, given an obnoxiously complex and long type hint, like prop: list[set[list[list[str] | set[int]]]], how do I access the internal values programmatically?
Here is a function that will recursively pretty print the type and all the types inside it, using typing.get_args as suggested by #user2357112 :
from typing import List, Set, Union
import typing
complex_type = Union[List[str], Set[int]]
def log_type_layers(typing_type, indent=4, depth=0):
current_type = typing_type
print(" "*indent*depth + str(current_type))
for subtype in typing.get_args(current_type):
log_type_layers(subtype, indent=indent, depth=depth+1)
log_type_layers(complex_type)
Output:
typing.Union[typing.List[str], typing.Set[int]]
typing.List[str]
<class 'str'>
typing.Set[int]
<class 'int'>
This question already has answers here:
Python: Make class iterable
(6 answers)
Closed 2 years ago.
I'm wondering if it's possible to make a class object iterable in Python (ie. a subclass of type, NOT an instance of a class).
I've tried the following code:
class Foo:
#classmethod
def __iter__(cls):
yield 1
print(next(Foo.__iter__())) # prints 1
print(next(iter(Foo))) # TypeError: 'type' object is not iterable
Turns out it's possible with metaclasses.
class Foo(type):
def __iter__(self):
yield self.baz
class Bar(metaclass=Foo):
baz = 1
print(type(Bar)) # prints "<class '__main__.Foo'>"
print(next(Bar.__iter__())) # prints "1"
print(next(iter(Bar))) # prints "1"
Thanks #DanielB for pointing me in the right direction.
This isn't possible, as it would imply that all type objects are iterable - as you stated, classes are of type type. The underlying reason for this is that the __iter__ method is looked up on the type, not the value. E.g., in:
for i in Foo:
print(i)
Python will look up type(Foo).__iter__, not Foo.__iter__.
This question already has answers here:
Should I, and how to, add methods to int in python?
(1 answer)
Can I add custom methods/attributes to built-in Python types?
(8 answers)
Closed 5 years ago.
If I have a class such as this
class foo():
def __init__(self, value = 0):
self.__value = value
def __set__(self, instance, value):
self.__value = value
def calc(self):
return self.__value * 3
def __repr__(self):
return str(self.__value)
I can now make a variable of the class foo and use it's functions.
n = foo(3)
print(n.calc())
No problems there but if I keep going with something like this.
n = 5
print(n.calc())
I will get an error, because I have now set n to an int object with the value 5 and thus does not have the calc() function.
I normally work with C++ so I'm confused because I thought that the __set__ function was supposed to override the = operator and then set __value to the value of 5 just like if I were to to use
operator=(int value)
In C++, I have looked for an explanation but have not found any.
All help appreciated.
As stated here.
The following methods only apply when an instance of the class
containing the method (a so-called descriptor class) appears in an
owner class (the descriptor must be in either the owner’s class
dictionary or in the class dictionary for one of its parents).
This question already has answers here:
How does Python's super() work with multiple inheritance?
(18 answers)
Closed 7 years ago.
when searching for attributes, Python looks in object g 1st. If I number each class named in the drawing below (2=2nd, 3=3rd, etc.) Could anyone show me the order in which all these classes are searched.
class A : pass
class B : pass
class C(A,object): pass
class D: pass
class E(D,B): pass
class F(B,C): pass
class G(E,F): pass
g = G()
This order:
>>> G.__mro__
(<class '__main__.G'>, <class __main__.E at 0x028412D0>, <class __main__.D at 0x
02841298>, <class '__main__.F'>, <class __main__.B at 0x02841260>, <class '__mai
n__.C'>, <class __main__.A at 0x02841228>, <type 'object'>)
>>> print ', '.join(klass.__name__ for klass in G.__mro__)
G, E, D, F, B, C, A, object
If you want to know how that order is computed, there isn't a good, short answer. The incomplete, short answer is that Python ensures that subclasses come before superclasses and classes earlier in a list of base classes come before classes later in a list of base classes. The long answer is the 40-page document about C3 linearization on python.org, although the actual algorithm isn't 40 pages.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument
Default values for arguments
I'm having trouble explaining how a list belonging to a class behaves.
>>> class A(object):
... def __init__(self, L=[]):
... self.L = L
...
>>> a1 = A()
>>> a2 = A()
>>> a1.L.append("test")
>>> print a1.L
['test']
>>> print a2.L
['test']
In this example, how did a2.L get a value in it? I only added an item to the list in a1. How is it that they're sharing the list now.
Thanks,
Henry
A brief summary of all the comments you will get:
The problem is nothing to do with the class. It's because you're storing the values in the default argument of a function, and default arguments are stored on the function objects.