在 Python 中,有多种类型和数据结构可用于存储和组织数据。以下是一些常见的类型和数据结构:
int
)、浮点数(float
)和复数(complex
)等。True
和 False
。除了上述基本类型和数据结构,Python 还提供了许多其他类型和数据结构,如字节串(bytes
)、字节数组(bytearray
)、范围(range
)、枚举(enum
)等。此外,还可以使用模块和库来引入自定义的数据结构和类型,以满足特定的编程需求。
这些类型和数据结构在 Python 中非常常用,开发者可以根据具体的需求选择合适的类型来存储和操作数据。
有序(Ordered)和无序(Unordered)是描述数据的排列方式或组织形式的概念。
有序指的是数据的元素按照一定的顺序进行排列,并且这个顺序是可以预测和可靠的。在有序数据中,元素之间存在一种明确的关系或结构。通过索引或位置,我们可以访问和获取特定位置的元素。常见的有序数据结构包括列表(List)、元组(Tuple)、字符串(String)等。
例如,一个列表 [1, 2, 3, 4]
是有序的,其中元素按照从左到右的顺序排列。我们可以使用索引来访问特定位置的元素,如 my_list[0]
表示获取列表中的第一个元素。
相反,无序指的是数据的元素没有明确的顺序或排列方式。元素在容器中不存在特定的位置或索引,因此不能准确地预测或确定元素的顺序。常见的无序数据结构包括集合(Set)、字典(Dictionary)等。
例如,一个集合 {1, 2, 3, 4}
是无序的,其中元素之间没有特定的顺序。我们不能使用索引来获取某个元素,只能通过成员关系判断一个元素是否存在于集合中。
需要注意的是,有序和无序仅描述了数据的排列方式,并不代表数据的值或内容的有序或无序。在有序数据结构中,元素的值仍然可以是无序的,而在无序数据结构中,元素的值也可以按一定的方式进行组织和排序。
可变(Mutable)和不可变(Immutable)是描述数据对象是否可以被修改的概念。
可变指的是数据对象的值可以被修改或改变。这意味着在对可变对象进行操作时,可以更改其内部的状态或内容,而对象的身份或标识不会改变。可变对象可以添加、删除或更新其元素。常见的可变对象包括列表(List)、字典(Dictionary)、集合(Set)等。
例如,对于一个列表 [1, 2, 3]
,我们可以执行操作来添加一个新元素,如 my_list.append(4)
,此时该列表就会改变并包含新的元素。
相反,不可变指的是数据对象的值不能被修改或改变。当尝试修改不可变对象时,实际上是创建了一个新的对象,而原始对象保持不变。不可变对象的值在创建后就无法更改。常见的不可变对象包括整数(int)、浮点数(float)、字符串(string)、元组(tuple)等。
例如,对于一个字符串 "Hello"
,我们不能直接在原始字符串上进行修改,但可以通过创建新的字符串来进行操作,如 new_string = my_string + " World"
,此时会生成一个新的字符串对象。
不可变对象的优点包括更安全和可靠。由于不可变对象不可更改,因此在多个引用之间共享时,不会出现意外的副作用或不一致的结果。
需要注意的是,对一个变量重新赋值并不改变原始对象的可变性。例如,对一个可变对象重新赋值后,该变量引用了一个新的对象,但原始对象仍然存在于内存中,因此它的内部状态可以被修改。而对一个不可变对象重新赋值时,会创建一个新的对象,原始对象也不会改变。
a = [1, 2, 3, 4]
print(id(a)) # 1534040865600
a.append(5)
print(id(a)) # 1534040865600
c = a
print(id(c)) # 2394275183424
b = a.copy()
print(id(b)) # 2989132595456
print(a == b) # True
print(a is b) # False
当你修改列表的时候,他的id不会改变。这就是可变
a = "cxk"
print(id(a)) # 2874637880752
a += "d"
print(a, id(a)) # 2874637880560
当你修改元组就压根不能修改
字符串可以修改,但是改后id会变,这就是不可变
在字典中,只有不可变的数据类型可以作为键(key)使用。这是因为字典的键需要具备哈希(hash)的特性,而哈希值是通过键的内容计算得到的。
以下是一些常见的可作为字典键的数据类型:
以下是一些不能作为字典键的数据类型:
需要注意的是,虽然字符串和整数是可哈希的,并且可以作为字典的键,但相同内容的字符串对象或整数对象,在内存中只有一个实例,并且具有相同的哈希值。这意味着当使用相同内容的字符串或整数作为键时,它们会被视为相同的键,并且只能在字典中出现一次。如果尝试使用列表、字典或集合作为键,则会引发 TypeError 异常。
闭包(Closure)是指在一个函数内部定义的函数,并且该内部函数可以访问外部函数的变量、参数以及定义的其他函数。闭包可以捕获外部函数的状态,包括局部变量、参数等,并将其保存起来,使得外部函数的状态在内部函数被调用时仍然保持有效。
在Python中,当一个内部函数引用了外部函数的变量时,就会形成一个闭包。闭包函数可以像普通函数一样被调用,并且可以访问外部函数的变量,即使外部函数已经执行结束。
下面是一个简单的示例:
pythonCopy Codedef outer_function(x):
def inner_function(y):
return x + y
return inner_function
closure = outer_function(10)
print(closure(5)) # 输出 15
上述代码中,outer_function
是一个外部函数,它接受一个参数 x
,并在内部定义了 inner_function
。inner_function
可以访问外部函数的参数 x
,并返回 x + y
的结果。
通过调用 outer_function(10)
,我们得到一个闭包 closure
,它绑定了 x
的值为 10。然后,我们再次调用 closure(5)
,实际上是调用了内部函数 inner_function
,并传入参数 y
值为 5。最终的结果是 10 + 5,即 15。
闭包在编程中有一些应用场景,其中一个常见的是延迟计算。通过使用闭包,我们可以将一些状态或变量的绑定延迟到函数被调用的时候,从而实现一些特定的功能,例如惰性求值、缓存等。
需要注意的是,在使用闭包时,要注意处理外部函数变量的生命周期,避免出现意外的问题,如变量泄漏等。
装饰器利用了闭包中内部函数可以访问外部函数参数的特征 和 函数可以当做参数传递的特征实现。
def logger(func):
def wrapper(*args, **kwargs):
print("Function {}() is called with arguments: {}, {}".format(func.__name__, args, kwargs))
result = func(*args, **kwargs)
print("Function {}() returns: {}".format(func.__name__, result))
return result
return wrapper
@logger
def add(a, b):
return a + b
add(2, 3) # 输出: Function add() is called with arguments: (2, 3), {}
# Function add() returns: 5