How to access args of generic class [duplicate] - python

This question already has an answer here:
Access type argument in any specific subclass of user-defined Generic[T] class
(1 answer)
Closed 4 months ago.
If I have a class A:
T = TypeVar("T")
class A(Generic[T]):
a: T
How do I access the Generic[T] with the type-object A
typing.get_origin(A[...]).__bases__ just returns a <class 'typing.Generic'> instead of typing.Generic[~T]

You are looking for __orig_bases__. That is set by the type metaclass when a new class is created. It is mentioned here in PEP 560, but is otherwise hardly documented.
This attribute contains (as the name suggests) the original bases as they were passed to the metaclass constructor in the form of a tuple. This distinguishes it from __bases__, which contains the already resolved bases as returned by types.resolve_bases.
Here is a working example:
from typing import Generic, TypeVar
T = TypeVar("T")
class A(Generic[T]):
a: T
class B(A[int]):
pass
print(A.__orig_bases__) # (typing.Generic[~T],)
print(B.__orig_bases__) # (__main__.A[int],)
Since it is poorly documented, I would be careful, where you use it. If you add more context to your question, maybe we'll find a better way to accomplish what you are after.
Possibly related or of interest:
Access type argument in any specific subclass of user-defined Generic[T] class

Related

why do we pass self on all class methods? [duplicate]

This question already has answers here:
What is the purpose of the `self` parameter? Why is it needed?
(26 answers)
Closed 1 year ago.
I know that some of you will think It's a stupid question but I will ask anyway.
why do we need to pass 'self' on all class methods can't we use it without passing it like this:
class Player:
def __init__(name):
self.name = name
def print_player_name():
print(self.name)
Try it. It won't work because self is not defined. The name "self" is just established, but you could name it whatever you want. It refers to the object of the class on which the method is called.
Yes, you can do it but you have to mention it as a static method. Self represents the instance of the class. In simple words, self represents the object on which it is being executed. When you create an object, all variables change their values based on different object of same class. Every class needs object as it's argument because for different object, different values are assigned
self represents object of class on which method is called you don't always need to name it self[standard convention] any valid variable name is allowed in python to do this but it should be first argument of non-classmethods and should be replace self as in if you run this python will work as expected :
class Player:
def __init__(hello, name):
hello.name = name
def print_player_name(hello):
print(hello.name)
It's very simple that's the official Python convention. In official docs we can read about it.
"Often, the first argument of a method is called self. This is nothing
more than a convention: the name self has absolutely no special
meaning to Python. Note, however, that by not following the convention
your code may be less readable to other Python programmers, and it is
also conceivable that a class browser program might be written that
relies upon such a convention."

Can python class reference nonexistent variable and method? [duplicate]

This question already has answers here:
What is a mixin and why is it useful?
(18 answers)
Closed 2 years ago.
class SoftDeleteMixin(object):
deleted_at = Column(DateTime)
deleted = Column(types.SoftDeleteInteger, default=0)
def soft_delete(self, session):
"""Mark this object as deleted."""
self.deleted = self.id
self.deleted_at = timeutils.utcnow()
self.save(session=session)
In class SoftDeleteMixin method soft_delete, it references nonexistent self.id and self.save. Why can it do that in python?
Note: the focus is the class can reference nonexistent variable and method, not that it is a Mixin class.
If you instantiate a SoftDeleteMixin class and call the soft_delete method, you'll get an AttributeError.
If as you said in the comment those attributes are instantiated somewhere else, even in a child class, and you call soft_delete on a child class instance, it works because the attribute is there at the time the method is called.
To explain it in a simple way, python is an interpreted language, and except for syntax it does not perform too much checks on the whole file when executing the code, until that actual line is actually executed.
So yes, you could think it's a bad design but it is not, it's an accepted practice (see this question for more details) and it is allowed by the laguage. You can define methods which reference attributes not defined in a __init__ method or as class attributes or whatever. The important thing is that the istance has the attribute when the method is executed. It does not matter where or when the attribute is actually defined.
The word "mixin" in the class name means that this class is intended to be inherited by a class that already declares id and save(). If you try to use it by itself, it will cause errors.

Adding `__getattr__` method to an existing object instance [duplicate]

This question already has answers here:
Overriding special methods on an instance
(5 answers)
Closed 3 years ago.
I would like this to work:
import types
def new_getattr(self, *args, **kwargs):
return 2
class A:
def __init__(self):
pass
a = A()
a.__getattr__ = types.MethodType(new_getattr, a)
print(a.anything)
Right now, it throws AttributeError: A instance has no attribute 'anything'.
I tried different solutions proposed here and they work, but not for __getattr__.
If I do print(a.__getattr__('anything')), it actually prints 2; the problem is that my __getattr__ method is not called automatically when I do a.anything.
As a side note, in my actual implementation, I cannot modify the definition of the class A, nor can I type its name and do something like A.__getattr__ = ... (which would work) because I need this to be generic and independent of the class name.
Edit: I ended up doing it like this:
a.__class__.__getattr__ = new_getattr.
You can not - __dunder__ names are resolved on the type, not per-instance. Custom __getattr__ will need to be defined directly on A.
See Special method lookup section of the datamodel documentation, specifically:
For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
Note: if you only have a reference to an instance, not the class, it is still possible to monkeypatch the type by assigning a method onto the object returned by type(a). Be warned that this will affect all existing instances, not just the a instance.

Is it ok to use children method in abstract class? pep8 says instance has no member [duplicate]

This question already has answers here:
Is it possible to make abstract classes?
(14 answers)
Closed 5 years ago.
I use pep8 in visual studio code and I just tried to write some abstract classes.
The problem is I get the error [pylint] E1101:Instance of 'MyAbstract' has no 'child_method' member because pep8 does not realise that the method is well defined, but in the child classes.
To illustrate my problem here is a code snippet that is reducted to the minimum for clarity:
class MyAbstract:
def some_method(self):
newinfo = self.child_method()
# use newinfo
class MyChild(MyAbstract):
def child_method(self):
# Do something in a way
class OtherChild(MyAbstract):
def child_method(self):
# Do the same thing in a different way
So my questions are:
Is it ok to write classes like this?
How would you solve the error? (disable error, use another pattern, ...)
Clarification
The MyAbstract class shouldn't be instanciated, and the child classes will inherit the some_method. The idea is to use it on child class instances.
If you want MyAbstract to be an abstract class with abstract method child_method, Python has a way of expressing that in the abc module:
import abc
class MyAbstract(metaclass=abc.ABCMeta):
#abc.abstractmethod
def child_method(self):
pass
def some_method(self):
newinfo = self.child_method()
do_whatever_with(newinfo)
Your linter will no longer complain about the nonexistent method, and as a bonus, Python will detect attempts to instantiate a class with unimplemented abstract methods.

Django: How do I get the model a model inherits from? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
get python class parent(s)
I have a:
class Animal(models.Model):
pass
class Cat(Aminal):
pass
class StreetCat(Cat):
pass
How can I find out the model a model inherits from?
You can get the direct superclass in python through __base__
>>> StreetCat.__base__ is Cat
>>> True
__bases__ will get you a tuple of all parent classes if you have multiple base classes class Foo(A, B)
Update thanks to OP: the following django method does not retrieve abstract base classes, as technically these are internal use methods for storing the foreign keys that tie each inherited model to their parents. Be warned!
Django also indirectly provides some helpers for inherited models which are shortcuts for the pure python methods of traversing the superclasses.
>>> StreetCat._meta.get_parent_list()
[Out] : Set([Class Animal, Class Cat])
InheritedClass.parents is an ordered dictionary of all parents, so the following would work to get the upper most parent if you wanted:
>>> StreetCat._meta.parents.keys()[-1]
You could also use a non django related method, something like
>>> StreetCat.__mro__[-3]
# once you know that BaseModel is an Object, and since all defined models subclass
# the BaseModel, [-3] is the first class that subclasses models.Model

Categories