Параметр функции вводит в Python

Защитное утверждение работает следующим образом: если первый предикат равен false, он not оценивает следующий предикат (ы).

Другими словами, вы можете считать запятую , оператора guard такой же, как оператор &&. Это то, что мы называем ленивой оценкой; Если вы проверили, как && работает , вы заметите, что rhs представляет собой автозаполнение возвращает логическое значение, но не логическое значение, что означает, что оно может даже не оцениваться (в случае lhs параметр равен false).

хотите узнать больше об автозаполнении? проверьте это !

Итак, для вашего случая вы можете объединить все предикаты (которые, я думаю, будут более читабельными ИМО) в одном выражении guard. [1117 ]

254
задан efotinis 23 September 2012 в 03:21
поделиться

9 ответов

Python строго типизирован, потому что каждый объект имеет тип, каждый объект знает свой тип, невозможно случайно или намеренно использовать объект типа «как если бы» это был объект другого типа, и все элементарные операции с объектом делегируются его типу.

Это не имеет ничего общего с именами . Имя в Python не «имеет тип»: если и когда имя определено, имя относится к объекту , а объект действительно имеет тип (но на самом деле это не заставляет тип использовать имя : имя есть имя).

Имя в Python может прекрасно относиться к различным объектам в разное время (как и в большинстве языков программирования, хотя и не на всех) - и нет ограничений на имя, например, если оно однажды ссылалось на объект типа X, тогда он навсегда ограничен ссылаться только на другие объекты типа X. Ограничения на имен не являются частью концепции «строгой типизации», хотя некоторые энтузиасты статической типизации (где имена действительно ограничиваются, и в статике, также как и во время компиляции), таким образом неправильно используют термин.

152
ответ дан 23 November 2019 в 02:46
поделиться

Я реализовал обертку, если кто-либо хотел бы указать типы переменных.

import functools

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for i in range(len(args)):
            v = args[i]
            v_name = list(func.__annotations__.keys())[i]
            v_type = list(func.__annotations__.values())[i]
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        v = result
        v_name = 'return'
        v_type = func.__annotations__['return']
        error_msg = 'Variable `' + str(v_name) + '` should be type ('
        error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
        if not isinstance(v, v_type):
                raise TypeError(error_msg)
        return result

    return check

Использование это как:

@type_check
def test(name : str) -> float:
    return 3.0

@type_check
def test2(name : str) -> str:
    return 3.0

>> test('asd')
>> 3.0

>> test(42)
>> TypeError: Variable `name` should be type (<class 'str'>) but instead is type (<class 'int'>)

>> test2('asd')
>> TypeError: Variable `return` should be type (<class 'str'>) but instead is type (<class 'float'>)

РЕДАКТИРОВАНИЕ

код выше не работает, если какой-либо из аргументов (или возврат) тип не объявляется. Следующее редактирование может помочь, с другой стороны, оно только работает на kwargs и не проверяет args.

def type_check(func):

    @functools.wraps(func)
    def check(*args, **kwargs):
        for name, value in kwargs.items():
            v = value
            v_name = name
            if name not in func.__annotations__:
                continue

            v_type = func.__annotations__[name]

            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ') '
            if not isinstance(v, v_type):
                raise TypeError(error_msg)

        result = func(*args, **kwargs)
        if 'return' in func.__annotations__:
            v = result
            v_name = 'return'
            v_type = func.__annotations__['return']
            error_msg = 'Variable `' + str(v_name) + '` should be type ('
            error_msg += str(v_type) + ') but instead is type (' + str(type(v)) + ')'
            if not isinstance(v, v_type):
                    raise TypeError(error_msg)
        return result

    return check

0
ответ дан 23 November 2019 в 02:46
поделиться

Как Алекс Мартелли объясняет ,

Нормальное, питоническое, предпочтительное решение почти всегда - "утиный ввод": попробуйте использовать аргумент, как если бы он был определенного желаемого типа, сделайте это в операторе try / except, перехватывая все исключения, которые могли бы возникнуть, если бы аргумент не был на самом деле этого типа (или любого другого типа, красиво имитирующего его ;-), и в предложении except попробуйте что-нибудь еще (используя аргумент «как если бы» он был другого типа).

Прочтите остальную часть его сообщения для получения полезной информации.

5
ответ дан 23 November 2019 в 02:46
поделиться

Python не волнует, что вы передаете его функциям. Когда вы вызываете my_func (a, b) , переменные param1 и param2 будут содержать значения a и b. Python не знает, что вы вызываете функцию с правильными типами, и ожидает, что программист позаботится об этом. Если ваша функция будет вызываться с разными типами параметров, вы можете обернуть код, обращающийся к ним, с помощью блоков try / except и оценивать параметры любым способом.

3
ответ дан 23 November 2019 в 02:46
поделиться

Python не является строго типизированным в смысле статической проверки типов или проверки типов во время компиляции.

Большая часть кода Python подпадает под так называемый «Duck Typing» - например, вы ищете метод read для объекта - вам все равно, если объект - это файл на диске или в сокете, вы просто хотите прочитать из него N байтов.

8
ответ дан 23 November 2019 в 02:46
поделиться

Вы не указали тип. Метод потерпит неудачу (во время выполнения), только если попытается получить доступ к атрибутам, которые не определены для переданных параметров.

Поэтому эта простая функция:

def no_op(param1, param2):
    pass

... не потерпит неудачу независимо от того, какие два аргумента будут переданы.

Однако эта функция:

def call_quack(param1, param2):
    param1.quack()
    param2.quack()

... потерпит неудачу во время выполнения, если param1 и param2 не имеют вызываемых атрибутов с именем quack.

14
ответ дан 23 November 2019 в 02:46
поделиться

Вы никогда не указываете тип; в Python есть концепция утиной типизации; в основном код, обрабатывающий параметры, делает определенные предположения о них - возможно, вызывая определенные методы, которые параметр должен реализовать. Если параметр имеет неправильный тип, то будет выброшено исключение.

В общем, именно ваш код должен убедиться, что вы передаете объекты нужного типа - нет компилятора, который бы обеспечил это заранее.

2
ответ дан 23 November 2019 в 02:46
поделиться

В Python все имеет тип. Функция Python будет делать все, что от нее требуется, если тип аргументов это поддерживает.

Пример: foo добавит все, что можно __ add __ ed;), не беспокоясь о его типе. Это означает, что во избежание неудач вы должны предоставлять только те вещи, которые поддерживают добавление.

def foo(a,b):
    return a + b

class Bar(object):
    pass

class Zoo(object):
    def __add__(self, other):
        return 'zoom'

if __name__=='__main__':
    print foo(1, 2)
    print foo('james', 'bond')
    print foo(Zoo(), Zoo())
    print foo(Bar(), Bar()) # Should fail
1
ответ дан 23 November 2019 в 02:46
поделиться

Во многих языках есть переменные определенного типа и значения. Python не имеет переменных; у него есть объекты, и вы используете имена для ссылки на эти объекты.

В других языках, когда вы говорите:

a = 1

, тогда (обычно целочисленная) переменная меняет свое содержимое на значение 1.

В Python

a = 1

означает «использовать имя a для ссылки на объект 1 ». В интерактивном сеансе Python вы можете сделать следующее:

>>> type(1)
<type 'int'>

Функция типа вызывается с объектом 1 ; так как каждый объект знает свой тип, для типа легко найти указанный тип и вернуть его.

Аналогичным образом, всякий раз, когда вы определяете функцию

def funcname(param1, param2):

, функция получает два объекта и называет их param1 и param2 , независимо от их типов. Если вы хотите убедиться, что полученные объекты относятся к определенному типу, запрограммируйте свою функцию так, как если бы они имеют требуемый тип (ы), и перехватите исключения, которые будут выброшены, если они не являются. Вызываемые исключения обычно: TypeError (вы использовали недопустимую операцию) и AttributeError (вы пытались получить доступ к несуществующему члену (методы также являются членами)).

10
ответ дан 23 November 2019 в 02:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: