Type

动态类型

Python是动态类型语言,这意味着变量并没有固定的类型。实际上,Python 中的变量和其他 语言有很大的不同,特别是静态类型语言。变量并不是计算机内存中被写入的某个值,它们 只是指向内存的 ‘标签’ 或 ‘名称’ 。因此可能存在这样的情况,变量 ‘a’ 先代表值1,然后变成 字符串 ‘a string’ , 然后又变为指向一个函数。

Python 的动态类型常被认为是它的缺点,的确这个特性会导致复杂度提升和难以调试的代码。 命名为 ‘a’ 的变量可能是各种类型,开发人员或维护人员需要在代码中追踪命名,以保证它 没有被设置到毫不相关的对象上。

这里有些避免发生类似问题的参考方法:

  • 避免对不同类型的对象使用同一个变量名

a = 1
a = 'a string'
def a():
    pass  # 实现代码

count = 1
msg = 'a string'
def func():
    pass  # 实现代码

使用简短的函数或方法能降低对不相关对象使用同一个名称的风险。即使是相关的不同 类型的对象,也更建议使用不同命名:

items = 'a b c d'  # 首先指向字符串...
items = items.split(' ')  # ...变为列表
items = set(items)  # ...再变为集合

重复使用命名对效率并没有提升:赋值时无论如何都要创建新的对象。然而随着复杂度的 提升,赋值语句被其他代码包括 ‘if’ 分支和循环分开,使得更难查明指定变量的类型。 在某些代码的做法中,例如函数编程,推荐的是从不重复对同一个变量命名赋值。Java 内的实现方式是使用 ‘final’ 关键字。Python并没有 ‘final’ 关键字而且这与它的哲学 相悖。尽管如此,避免给同一个变量命名重复赋值仍是是个好的做法,并且有助于掌握 可变与不可变类型的概念。

可变和不可变类型

Python提供两种内置或用户定义的类型。可变类型允许内容的内部修改。典型的动态类型 包括列表与字典:列表都有可变方法,如 list.append()list.pop(), 并且能就地修改。字典也是一样。不可变类型没有修改自身内容的方法。比如,赋值为整数 6的变量 x 并没有 “自增” 方法,如果需要计算 x + 1,必须创建另一个整数变量并给其命名。

my_list = [1, 2, 3]
my_list[0] = 4
print my_list  # [4, 2, 3] <- 原列表改变了

x = 6
x = x + 1  # x 变量是一个新的变量

这种差异导致的一个后果就是,可变类型是不 ‘稳定 ‘的,因而不能作为字典的键使用。合理地 使用可变类型与不可变类型有助于阐明代码的意图。例如与列表相似的不可变类型是元组, 创建方式为 (1, 2)。元组是不可修改的,并能作为字典的键使用。

Python 中一个可能会让初学者惊讶的特性是:字符串是不可变类型。这意味着当需要组合一个 字符串时,将每一部分放到一个可变列表里,使用字符串时再组合 (‘join’) 起来的做法更高效。 值得注意的是,使用列表推导的构造方式比在循环中调用 append() 来构造列表更好也更快。

# 创建将0到19连接起来的字符串 (例 "012..1819")
nums = ""
for n in range(20):
    nums += str(n)   # 慢且低效
print nums

# 创建将0到19连接起来的字符串 (例 "012..1819")
nums = []
for n in range(20):
    nums.append(str(n))
print "".join(nums)  # 更高效

更好

# 创建将0到19连接起来的字符串 (例 "012..1819")
nums = [str(n) for n in range(20)]
print "".join(nums)

最好Best

# 创建将0到19连接起来的字符串 (例 "012..1819")
nums = map(str, range(20))
print "".join(nums)

最后关于字符串的说明的一点是,使用 join() 并不总是最好的选择。比如当用预先 确定数量的字符串创建一个新的字符串时,使用加法操作符确实更快,但在上文提到的情况 下或添加到已存在字符串的情况下,使用 join() 是更好的选择。

foo = 'foo'
bar = 'bar'

foobar = foo + bar  # 好的做法
foo += 'ooo'  # 不好的做法, 应该这么做:
foo = ''.join([foo, 'ooo'])

注解

除了 str.join()+,您也可以使用 % 格式运算符来连接确定数量的字符串,但 PEP 3101 建议使用 str.format() 替代 % 操作符。

foo = 'foo'
bar = 'bar'

foobar = '%s%s' % (foo, bar) # 可行
foobar = '{0}{1}'.format(foo, bar) # 更好
foobar = '{foo}{bar}'.format(foo=foo, bar=bar) # 最好
Previous
Next