当前位置: 首页 > 面试题库 >

Python 3和静态类型

陶高峻
2023-03-14
问题内容

我并没有真正关注Python
3的开发,只是注意到一些有趣的新语法更改。特别是从此SO回答功能参数注释中:

def digits(x:'nonnegative number') -> "yields number's digits":
    # ...

我对此一无所知,我认为它可以用于在Python中实现静态类型!

经过一番搜索之后,似乎对Python中的(完全可选的)静态类型进行了很多讨论,例如PEP
3107
中提到的内容,以及“向Python添加可选的静态类型”(以及第2部分)

..但是,我不清楚这进展了多少。是否有使用参数注释的静态类型的实现?是否有任何参数化类型的想法将其纳入Python 3?


问题答案:

感谢您阅读我的代码!

确实,在Python中创建通用注释执行器并不难。这是我的看法:

'''Very simple enforcer of type annotations.

This toy super-decorator can decorate all functions in a given module that have 
annotations so that the type of input and output is enforced; an AssertionError is
raised on mismatch.

This module also has a test function func() which should fail and logging facility 
log which defaults to print.

Since this is a test module, I cut corners by only checking *keyword* arguments.

'''

import sys

log = print


def func(x:'int' = 0) -> 'str':
    '''An example function that fails type checking.'''
    return x


# For simplicity, I only do keyword args.
def check_type(*args):
    param, value, assert_type = args
    log('Checking {0} = {1} of {2}.'.format(*args))
    if not isinstance(value, assert_type):
        raise AssertionError(
            'Check failed - parameter {0} = {1} not {2}.'
            .format(*args))
    return value

def decorate_func(func):    
    def newf(*args, **kwargs):
        for k, v in kwargs.items():
            check_type(k, v, ann[k])
        return check_type('<return_value>', func(*args, **kwargs), ann['return'])

    ann = {k: eval(v) for k, v in func.__annotations__.items()}
    newf.__doc__ = func.__doc__
    newf.__type_checked = True
    return newf

def decorate_module(module = '__main__'):
    '''Enforces type from annotation for all functions in module.'''
    d = sys.modules[module].__dict__
    for k, f in d.items():
        if getattr(f, '__annotations__', {}) and not getattr(f, '__type_checked', False):
            log('Decorated {0!r}.'.format(f.__name__))
            d[k] = decorate_func(f)


if __name__ == '__main__':
    decorate_module()

    # This will raise AssertionError.
    func(x = 5)

鉴于这种简单性,乍一看这东西不是主流很奇怪。但是,我相信有充分的理由说明它 没有看起来那么有用
。通常,类型检查会有所帮助,因为如果添加整数和字典,很可能会犯一些明显的错误(并且如果您要讲的是合理的话, 显式要比隐式好

但是在现实生活中,您经常会混合使用与编译器所见的 计算机类型 相同但数量明显不同的 人类类型的数量 ,例如,以下代码段包含一个明显的错误:

height = 1.75 # Bob's height in meters.
length = len(sys.modules) # Number of modules imported by program.
area = height * length # What's that supposed to mean???

任何人应立即看到上面的行了一个错误,只要它知道变量的“人型”heightlength即使它看起来计算机 完全合法
的乘法intfloat

关于此问题的可能解决方案,还有很多要说的,但是强制执行“计算机类型”显然只是解决方案的一半,因此,至少在我看来,这 比根本没有解决方案还要糟糕
。这也是为什么 Systems Hungarian 是一个糟糕的主意,而 Apps Hungarian 是一个很棒的主意的原因。
乔尔·斯波斯基(Joel
Spolsky)的
信息量非常丰富。

现在,如果有人要实现某种Pythonic第三方库,该库将自动将其 人类类型 分配给现实数据,然后小心地将其转换为类似类型width * height -> area并使用功能注释强制执行该检查,那么我认为这将是一种类型检查人真的可以使用!



 类似资料:
  • 一个机器或语言是用来计算的,根据计算机模型的定义,其操作的是存储器里的数据,就现在流行的用二进制实现的计算机中(曾出现过三进制计算机),数据本质都是0和1,但机器毕竟是为人服务的,解决的是现实问题,它操作的数据需要有现实的含义,所以基本上所有语言都有类型系统,即便是汇编和机器语言,也有整数和浮点的区别 类型系统是很复杂的理论,值得用一本厚书来写,好点的资料有《类型与程序设计语言》,但我没看懂,因为

  • 我在看一个项目,我发现了一些很奇怪的东西。 现在,我认为唯一的两个优点是,在非静态容器中封装时,命名更加清晰,并且可以传递的参数更少。 但我想知道这是不是一个好主意,通过设计来包装静态类与非静态?如果有的话,还有哪些其他原因?因为我认为创建一个静态并对其进行调用是可以的。但是这个项目特意将所有静态类打包;我也不知道为什么。

  • 在讲类方法和静态方法之前,先来看一个简单的例子: class A(object): def foo(self): print 'Hello ', self >>> a = A() >>> a.foo() Hello, <__main__.A object at 0x10c37a450> 在上面,我们定义了一个类 A,它有一个方法 foo,然后我们创建了一个对象 a,并调用

  • 问题内容: Simmilar问题(与Python2相关:Python:检查方法是否为静态) 让我们考虑以下类定义: 在Python 3中,一切都不再是功能了,因此与Python 2相关的答案将不再起作用。 正如我所说的,一切都是函数,因此我们可以调用,但是我们当然不能调用(参数不匹配)。但是,如果我们做一个实例,我们叫Python的传递给函数的作为第一个参数。调用阻止发送或捕获-,因此必须有一种方

  • 问题内容: 我有一个充满实用程序功能的类。实例化它的实例没有语义,但是我仍然想调用它的方法。处理此问题的最佳方法是什么?静态课?抽象? 问题答案: 标记为final的类上的私有构造函数和静态方法。

  • 问题内容: 只是为了澄清我正在考虑的这个权利,在Java中,静态字段是整个类使用的变量/字段,还是可以用于引用该类的所有对象?非静态字段是由对象定义的变量吗?并且与对象1引用相同类的第二个对象可以具有与对象1的静态字段不同的值吗? 问题答案: 与实例变量不同,在创建该类的实例之前,可以访问该类中的静态字段或静态类变量。在运行时创建该类的实例时,将创建该类中的实例变量(非静态变量)。因此,直到创建该

  • 我想澄清一下,在java中,静态字段是整个类使用的变量/字段,或者可以被引用该类的所有对象使用?非静态字段是由对象定义的变量?第二个对象引用与对象1相同的类,它可以对对象1的静态字段具有不同的值?

  • 问题内容: 我知道不可能在一个类中重写一个方法。但是,有没有办法使用非静态方法作为静态方法呢?例如,我有一个加数字的方法。我希望此方法在没有对象的情况下有用。是否可以在不创建其他方法的情况下执行类似的操作? 编辑:我的意思是,如果我将一个方法设为静态,我将需要它接受参数,如果我创建了一个已经设置了变量的对象,那么再次对具有相同参数的对象调用函数将非常不舒服。 我知道代码不正确,但是我想展示自己想做