Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - how to pass to a function argument type of a class object (typing)

I suppose that came with python 3.7 (not sure), the possibility to pass to a function not only the variable name but also the type of the variable. What I would like to know is if there is any possibility of passing the type of a particular class.

The same way you could pass:

def foo_func(i: int) -> None:
    pass

If I have a class let's say:

class foo_class(object):
    pass

How could I transform the foo_func to receive the foo_classinstead of the inttype?

Furthermore, if foo_class was an inheritance of another class could I impose a more general type from the parent? For instance, if I would have,

class A(foo_class):
     pass

class B(foo_class):
     pass

How could I pass A or B based on its parent?

I mean something like:

def foo_func(obj: foo_class_type) -> None:
    pass

foo_func(A())
foo_func(B())
like image 240
Sergio Cavaleiro Costa Avatar asked Apr 18 '19 17:04

Sergio Cavaleiro Costa


People also ask

Can you pass any type of object as an argument to a function Python?

A function can take multiple arguments, these arguments can be objects, variables(of same or different data types) and functions. Python functions are first class objects.

How do you pass a class instance as a function argument in Python?

Example: A Class Method Passed as an Argument In this example, we define a class and its objects. We create an object to call the class methods. Now, to call a passed method or function, you just use the name it's bound to in the same way you would use the method's (or function's) regular name.

How do you use a class object as a parameter in Python?

Python Class Object At first, you put the name of the new object which is followed by the assignment operator and the name of the class with parameters (as defined in the constructor). Remember, the number and type of parameters should be compatible with the parameters received in the constructor function.

Can we pass class as function arguments?

Passing and Returning Objects in C++ In C++ we can pass class's objects as arguments and also return them from a function the same way we pass and return other variables.


1 Answers

Depending on whether you meant to pass a class (type) or an instance of a class, you’re looking for either typing.Type or simply the class.

Here’s a simple example to explain both situations:

from typing import Type, TypeVar


class Vehicle:
    def __init__(self):
        print("Creating a %s" % self.__class__.__name__)

    def move(self):
        print("This %s is moving…" % self.__class__.__name__)

TVehicle = TypeVar("TVehicle", bound=Vehicle)

class Car(Vehicle):
    def honk(self) -> None:
        print("tuuuuut")

class Bike(Vehicle):
    def ring(self) -> None:
        print("ring")

class Dog:
    def bark(self) -> None:
        print("woof!")


def move(v: Vehicle) -> None:
    v.move()

def instantiate(class_to_instantiate: Type[TVehicle]) -> TVehicle:
    return class_to_instantiate()  # create an instance

move(Bike())
move(Car())

instantiate(Bike).ring()
instantiate(Car).honk()
#instantiate(Dog)

Car and Bike inherit from Vehicle, so they both get at least the move method and the custom __init__, which reveals the name of the class that invoked it.

Now, in the first function, move, one simply wants to specify that the argument v should be an instance of a Vehicle. The function calls Vehicle’s move method, which will reveal the name of the instance’s class from which the call originated.

In the second function, instantiate, the goal is to create an instance of a class. This works through type variables, which allow you in this example to specify that there’s a relation between the function’s input argument and output argument: if I were to call instantiate(Bike), I want the return type to be an instance of the Bike class, so that I may legally call its ring method. If you were to replace the TVehicle in this function definition simply by Vehicle, your type checking program would complain, because the return type would then be an instance of the Vehicle class, for which you do not have a guarantee that the ring method exists. Finally, the Type part that you see in the argument of instantiate simply allows you to call the function with a class, so not with an instance of that class. This is useful e.g. in cases where you want to delay instantiation of a class.

Note that this is an example to explain how to do it. In a more professional setting, Vehicle would likely be an abstract base class and some methods here could be given as class methods.

Side notes on your code example:

  1. Note that if you don’t intend to write code that also works in Python2, you shouldn’t inherit from object (ref).
  2. Classes are typically written with CapWord names, as specified in PEP8, the Python style guide. Following this style makes your code more easily understandable by other developers.
like image 87
Oliver W. Avatar answered Sep 23 '22 10:09

Oliver W.