做阿里渠道的销售要有哪些网站,广告公司网站建设策划书,湖北省建设工程网站,做网站的cnfg1. 如何理解Python中的深浅拷贝
浅拷贝#xff08;Shallow Copy#xff09;创建一个新的对象#xff0c;该对象的内容是原始对象的引用。这意味着新对象与原始对象共享相同的内存地址#xff0c;因此对于可变对象来说#xff0c;如果修改了其中一个对象#xff0c;另一个…
1. 如何理解Python中的深浅拷贝
浅拷贝Shallow Copy创建一个新的对象该对象的内容是原始对象的引用。这意味着新对象与原始对象共享相同的内存地址因此对于可变对象来说如果修改了其中一个对象另一个对象也会受到影响。浅拷贝通常使用copy模块的copy()函数或者对象的copy()方法来完成。
下面是一个浅拷贝的示例
import copyoriginal_list [1, 2, [3, 4]]
copied_list copy.copy(original_list)print(original_list) # [1, 2, [3, 4]]
print(copied_list) # [1, 2, [3, 4]]# 修改原始列表中的元素
original_list[0] 10
original_list[2][0] 30print(original_list) # [10, 2, [30, 4]]
print(copied_list) # [1, 2, [30, 4]]在上面的示例中copy.copy()函数创建了original_list的浅拷贝copied_list。当我们修改original_list时copied_list中的嵌套列表也会受到影响。
深拷贝Deep Copy创建一个新的对象该对象的内容是原始对象及其所有嵌套对象的副本。这意味着新对象在内存中是完全独立的对其中一个对象的修改不会影响另一个对象。深拷贝通常使用copy模块的deepcopy()函数或者对象的deepcopy()方法来完成。
下面是一个深拷贝的示例
import copyoriginal_list [1, 2, [3, 4]]
deep_copied_list copy.deepcopy(original_list)print(original_list) # [1, 2, [3, 4]]
print(deep_copied_list) # [1, 2, [3, 4]]# 修改原始列表中的元素
original_list[0] 10
original_list[2][0] 30print(original_list) # [10, 2, [30, 4]]
print(deep_copied_list) # [1, 2, [3, 4]]在上面的示例中copy.deepcopy()函数创建了original_list的深拷贝deep_copied_list。即使我们修改original_listdeep_copied_list中的嵌套列表也不会受到影响。
需要注意的是深拷贝可能会比浅拷贝更耗费时间和内存因为它需要递归地复制所有嵌套对象。因此在处理大型对象或嵌套层级很深的对象时需要谨慎使用深拷贝。
总结起来浅拷贝创建一个新对象该对象与原始对象共享部分内存而深拷贝创建一个完全独立的新对象它复制了原始对象及其所有嵌套对象的内容。根据需求选择适当的拷贝方式可以帮助我们正确地处理对象并避免意外的副作用。
2. 谈谈 is 和 的区别
在Python中is和是用于比较对象的运算符它们具有不同的功能和用途。
is运算符用于比较两个对象的身份标识即它们是否指向同一个内存地址。如果两个对象具有相同的身份标识即它们是同一个对象那么is运算符返回True否则返回False。
运算符用于比较两个对象的值是否相等。它会比较两个对象的内容而不关心它们是否指向同一个内存地址。如果两个对象的值相等运算符返回True否则返回False。
下面是一个示例展示了is和运算符的区别
list1 [1, 2, 3]
list2 [1, 2, 3]
list3 list1print(list1 is list2) # Falselist1和list2不是同一个对象
print(list1 is list3) # Truelist1和list3是同一个对象print(list1 list2) # Truelist1和list2的值相等在上面的示例中list1和list2虽然具有相同的值但它们是不同的对象因此list1 is list2返回False。另一方面list1和list3指向同一个对象因此list1 is list3返回True。而list1 list2返回True因为它们的值相等。
需要注意的是对于简单的值类型如整数、字符串等is和的结果通常是一致的。但对于可变对象如列表、字典等is和的结果可能不同因为可变对象的身份标识可能相同但值不同。
总结起来is运算符用于比较两个对象的身份标识即它们是否指向同一个内存地址而运算符用于比较两个对象的值是否相等。在编写代码时需要根据具体的需求选择适当的运算符。如果要比较对象的值应使用运算符如果要比较对象的身份标识应使用is运算符。
3. 说说闭包和装饰器的概念
**闭包Closure**是指在一个函数内部定义的函数并且内部函数可以访问外部函数的变量。闭包可以捕获和保持外部函数的状态即使外部函数已经执行完毕内部函数仍然可以使用那些被捕获的变量。闭包在需要保持某些状态或者提供数据隐藏时非常有用。
下面是一个闭包的例子
def outer_function(x):def inner_function(y):return x yreturn inner_functionclosure outer_function(10)
result closure(5)
print(result) # 输出 15在上面的例子中outer_function是外部函数它接受一个参数x并返回一个内部函数inner_function。内部函数inner_function可以访问外部函数outer_function的参数x即使在outer_function执行完毕后仍然有效。
**装饰器Decorator**是一种特殊的闭包用于修改或增强函数的功能而不修改函数本身的定义。装饰器通常用于添加额外的代码例如日志记录、性能分析、输入验证等。装饰器可以在不修改原函数代码的情况下对函数进行包装和扩展。
下面是一个简单的装饰器的例子
def logger(func):def wrapper(*args, **kwargs):print(fCalling function: {func.__name__})result func(*args, **kwargs)print(fFunction {func.__name__} executed.)return resultreturn wrapperlogger
def add(a, b):return a bresult add(2, 3)
print(result) # 输出 5在上面的例子中logger是一个装饰器函数它接受一个函数作为参数并返回一个新的函数wrapper。wrapper函数在调用被装饰的函数之前和之后打印日志信息。
通过使用logger语法我们将装饰器应用到add函数上。当调用add函数时实际上是调用了被装饰后的wrapper函数从而实现了日志记录的功能增强。
实际应用中闭包和装饰器有许多用例。以下是一些示例
计时器使用装饰器记录函数的执行时间。认证和权限控制使用装饰器验证用户身份和控制访问权限。缓存使用闭包实现函数的结果缓存以避免重复计算。日志记录使用装饰器将函数的调用和返回值记录到日志文件中。输入验证使用装饰器对函数的输入参数进行验证和过滤。
4. 用装饰器实现一个日志记录的例子
def logger(func):def wrapper(*args, **kwargs):print(fCalling function: {func.__name__})print(fArguments: {args}, {kwargs})result func(*args, **kwargs)print(fFunction {func.__name__} executed.)print(fResult: {result})return resultreturn wrapperlogger
def add(a, b):return a bresult add(2, 3)5. 可变对象和不可变对象有哪些
**不可变对象Immutable objects**是指创建后不能被修改的对象。当对不可变对象进行操作时会创建一个新的对象。以下是一些常见的不可变对象
**数字Numbers**包括整数int、浮点数float、复数complex等。**布尔值Booleans**True和False。**字符串Strings**一旦创建字符串的值就不能被修改。**元组Tuples**元组是一种有序且不可变的集合。
以下是不可变对象的一些特点
不可变对象的值在创建后不能被修改对其进行操作会创建一个新的对象。不可变对象在多线程环境下是线程安全的因为其状态不可变。不可变对象可以作为字典的键或集合的元素因为它们的哈希值不会变化。
**可变对象Mutable objects**是可以修改的对象即可以改变对象的值或状态。以下是一些常见的可变对象
**列表Lists**列表是有序且可变的集合可以通过索引进行修改。**字典Dictionaries**字典是无序的键值对集合可以通过键进行修改。**集合Sets**集合是无序且唯一的元素集合可以进行添加、删除等操作。
以下是可变对象的一些特点
可变对象的值可以在创建后被修改对其进行操作会直接修改原始对象。可变对象在多线程环境下需要进行同步操作以避免并发修改导致的问题。可变对象不能作为字典的键或集合的元素因为其值的变化可能导致哈希值的变化。
6. 什么是值传递和引用传递
**值传递Pass-by-Value**是指将实际参数的值复制一份传递给函数或赋值给新变量。在这种情况下函数或新变量操作的是复制后的值对原始变量的修改不会影响到原始值。
**引用传递Pass-by-Reference**是指将实际参数的引用或地址传递给函数或赋值给新变量。在这种情况下函数或新变量操作的是原始变量所在的内存地址对变量的修改会直接影响到原始值。
在Python中参数传递是通过引用传递的方式进行的。也就是说函数或方法的参数传递的是对象的引用而不是对象本身的副本。这意味着如果在函数内部对引用的对象进行修改会影响到原始对象。
下面是一个示例
def modify_list(lst):lst.append(4)my_list [1, 2, 3]
modify_list(my_list)
print(my_list) # 输出 [1, 2, 3, 4]
在上面的例子中我们定义了一个modify_list函数它接受一个列表作为参数并向列表中添加一个元素。当我们调用modify_list(my_list)时实际上是将my_list的引用传递给modify_list函数。在函数内部我们通过引用对列表进行修改添加了一个新元素。这导致原始列表my_list也被修改输出结果为[1, 2, 3, 4]。
在实际使用中我们需要根据需求选择值传递还是引用传递。一般来说如果希望在函数内部修改原始对象可以使用引用传递。如果希望保持原始对象不变可以使用值传递或传递对象的副本。
需要注意的是在Python中虽然参数传递是通过引用传递的方式但对于不可变对象如整数、字符串、元组因为其值无法修改所以表现类似于值传递。而对于可变对象如列表、字典、集合因为其值可以修改所以表现类似于引用传递。
值传递例子
def modify_value(value):value value 1x 10
modify_value(x)
print(x) # 输出 10
在上面的例子中我们定义了一个modify_value函数它接受一个整数参数value。在函数内部我们对value进行加1操作。然而即使在函数内部对value进行了修改原始变量x的值并没有改变。这是因为整数是不可变对象函数调用时发生的是值传递传递的是x的值的副本而不是x本身
最后感谢每一个认真阅读我文章的人礼尚往来总是要有的虽然不是什么很值钱的东西如果你用得到的话可以直接拿走
行动吧在路上总比一直观望的要好未来的你肯定会感谢现在拼搏的自己如果想学习提升找不到资料没人答疑解惑时请及时加入群 731789136里面有各种测试开发资料和技术可以一起交流哦。 这些资料对于【软件测试】的朋友来说应该是最全面最完整的备战仓库这个仓库也陪伴上万个测试工程师们走过最艰难的路程希望也能帮助到你