简体   繁体   中英

Python type hinting: return type based on attribute

Trying out type hinting, and I'm having a bit of trouble wrapping my head around something:

class Node(object):
    credentials_class = credentials.BaseCredentials

    @property
    def credentials_instance(self) -> [credentials_class]:
        return self.credentials_class(self.credentials_data)


class OtherNode(Node):
    credentials_class = credentials.OtherCredentials  # subclass of BaseCredentials    

How can I make it so that OtherNode().credentials_instance returns the type that is specified in credentials_class , for all subclasses of Node ?

The credentials_class attribute is not required, if there is some other way for me to tell the system that "this node's credentials_instance property returns this instance type", that would be fine.

The answer is generics . By making Node generic and parametrizing with the credentials class, you can specify the types as you want them to work. The downside is, the topmost class cannot assign a default value to credentials_class , because it'd conflict with it being generic.

from typing import Type, Generic, TypeVar

CredentialsClassT = TypeVar("CredentialsClassT", bound=credentials.BaseCredentials)

class Node(Generic[CredentialsClassT]):
    credentials_class: Type[CredentialsClassT]

    @property
    def credentials_instance(self) -> CredentialsClassT:
        return self.credentials_class(self.credentials_data)

# example usage
class BaseNode(Node[credentials.BaseCredentials]):
    credentials_class = credentials.BaseCredentials

class OtherNode(Node[credentials.OtherCredentials]):
    credentials_class = credentials.OtherCredentials  # subclass of BaseCredentials    

With that typing in place, eg.

reveal_type(OtherNode.credentials_instance)

will make MyPy print not: Revealed type is 'credentials.OtherCredentials' as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM