Używam Pythona 3.7, programuję przy użyciu PyCharm.

Chodzi mi o prostą metodę, która przyjmuje typ, na przykład type (str), type (int) i tak dalej. Nie wydaje mi się, żeby to działało.

Chcę mieć możliwość przekazania typu, a następnie przetestowania go w ramach metody.

Pokażę ci, że mam:

def TypeTestMethod(self, t):
    print(f't is {t} | Type of t: {type(t)}')

    if(t == type(str)):
        print(f'Type is str')

    if(t == type(int)):
        print('Type is int')

Kiedy to nazywam, przekazuję typ. Przykład połączenia wyglądałby następująco:

TypeTestMethod(t=type(str))

Mam nadzieję, że ten typ (str) zostanie przekazany, a następnie trafi w pierwszą instrukcję if, ale nie w drugą. W tej chwili tak się nie dzieje; trafia w oba instrukcje i wypisuje zarówno „Type is str” , jak i „Type is int”.

Jeśli jesteś ciekawy pierwszej instrukcji print, wypisuje ona następujące informacje:

t is <class 'type'> | Type of t: <class 'type'>

Z jakiegoś powodu dane w metodzie nie działają poprawnie.

Widzę dwa rozwiązania, ale żadne z nich nie wydaje się w ogóle eleganckie. Pierwszym jest podanie przykładowej zmiennej żądanego typu. Wolałbym nie deklarować więcej pamięci niż potrzebuję, jeśli to konieczne, więc jeśli chodzi o przykład z datą i godziną, może to być kłopotliwe. Drugim jest utworzenie własnego wyliczenia i zrobienie tego w ten sposób. Jest to oczywiście możliwe w przypadku bieżącego zadania, ale wydaje się niezgrabne. Typy są już w systemie - na pewno mogę zamiast tego użyć istniejących.

Na pewno jest sposób.

0
TheFaithfulLearner 2 kwiecień 2020, 15:09

3 odpowiedzi

Najlepsza odpowiedź

Na podstawie kombinacji naszych komentarzy myślę , czego chcesz

def type_test_function(self, t):
    print(f't is {t} | Type of t: {type(t)}')

    if issubclass(t, str):  # Or t is str, if you don't want to catch subclasses
        print(f'Type is str')

    if issubclass(t, int):
        print('Type is int')

type(str) podaje typ typu str, czyli sam type. Twój argument powinien być albo type("some string") albo po prostu str.

type_test_function(str)
type_test_function(int)
# etc.
1
chepner 2 kwiecień 2020, 12:22

type to właściwie klasa i to metaklasa for object - który sam jest klasą bazową dla wszystkich klas (przynajmniej w Py3). Więc kiedy wywołujesz swoją funkcję za pomocą

TypeTestMethod(t=type(str))

To, co przekazujesz jako wartość, jest już klasą type, stąd wynik, który otrzymujesz. Następnie w swojej funkcji:

if(t == type(str)):
    print(f'Type is str')

Tutaj znowu porównujesz t z type(str), które nadal jest klasą type.

Twoje pytanie nie określa jasno, co naprawdę próbujesz tutaj zrobić, ale oczywiście nie rozumiesz systemu typów Pythona, więc sugeruję przeczytaj doc na temat modelu danych Pythona i przetestuj różne rzeczy w powłoce Pythona (głównie do tego służy), aby dokładnie sprawdzić, czy rozumiesz. Kilka wbudowanych funkcji, które również mogą Cię zainteresować, to isinstance(obj, cls) i issubclass(cls, othercls).

0
bruno desthuilliers 2 kwiecień 2020, 13:02

Jeśli nie masz nic przeciwko posiadaniu wielu funkcji, możesz użyć functools.singledispatch

Definiujesz funkcję ogólną, a następnie rejestrujesz funkcje wyspecjalizowane dla różnych typów (wysyłane przy pierwszym argumencie). Funkcja ogólna jest wywoływana, jeśli żadna funkcja specjalistyczna nie pasuje do argumentu.

@singledispatch
def test_method_type(arg):
    print('Generic output')

@test_method_type.register(int)
def _(arg):
    print('Integer argument')

@test_method_type.register(str)
def _(arg):
    print('String argument')

test_method_type(42)
Integer argument

test_method_type('hello')
String argument

test_method_type(b'hello')
Generic output

Jeśli używasz adnotacji typu, typ wysyłki zostanie wywnioskowany na podstawie pierwszego argumentu funkcji

@test_method_type.register
def _(arg: list):
    print('List argument')

W Pythonie 3.8 jest też functools.singledispatchmethod dekorator metod.

from functools import singledispatchmethod


class Typer:

    @singledispatchmethod
    def test_method_type(self, arg):
        print('Generic output')

    @test_method_type.register(bool)
    def _(self, arg):
        print('Boolean argument')

    @test_method_type.register(int)
    def _(self, arg):
        print('Integer argument')

    @test_method_type.register(str)
    def _(self, arg):
        print('String argument')


typer = Typer()

typer.test_method_type(False)
Boolean argument

typer.test_method_type(42)
Integer argument

typer.test_method_type('hello')
String argument

typer.test_method_type(None)
Generic output
0
snakecharmerb 2 kwiecień 2020, 13:06