学无止境

少年辛苦终身事,莫向光阴惰寸功。——唐·杜荀鹤《题弟侄书堂》


Python高级特性:对象比较、拷贝机制与作用域

1. == 与 is 的区别

1.1 基本概念

  • ==:比较对象的值是否相等
  • is:比较对象的身份(内存地址)是否相同

1.2 详细示例

# 值比较
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b)  # True(值相等)
print(a is b)  # False(不同对象)

# 小整数对象池
x = 256
y = 256
print(x is y)  # True(在对象池范围内)

m = 257
n = 257
print(m is n)  # False(超出对象池范围)

1.3 Python对象池机制

  1. 小整数对象池:范围为[-5, 257)
  2. 字符串驻留机制:相同的字符串常量共用同一个对象
# 字符串驻留示例
s1 = "hello"
s2 = "hello"
print(s1 is s2)  # True

# 长字符串或包含空格的字符串可能不会驻留
s3 = "hello world"
s4 = "hello world"
print(s3 is s4)  # 结果可能是False

2. 拷贝机制

2.1 赋值操作

# 简单赋值是引用传递
list1 = [1, 2, [3, 4]]
list2 = list1
list2[0] = 100
print(list1)  # [100, 2, [3, 4]]
print(list2)  # [100, 2, [3, 4]]

2.2 浅拷贝(Shallow Copy)

浅拷贝创建新对象,但内部对象引用不变。

import copy

# 浅拷贝的三种方式
# 1. 使用copy模块
list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1)

# 2. 使用切片
list3 = list1[:]

# 3. 使用工厂函数
list4 = list(list1)

# 修改测试
list2[0] = 100
list2[2][0] = 300
print(list1)  # [1, 2, [300, 4]]
print(list2)  # [100, 2, [300, 4]]

2.3 深拷贝(Deep Copy)

深拷贝创建新对象,并递归地复制所有内部对象。

import copy

# 深拷贝示例
original = [1, [2, 3], {'a': 4}]
deep_copied = copy.deepcopy(original)

# 修改测试
deep_copied[1][0] = 200
deep_copied[2]['a'] = 400

print(original)     # [1, [2, 3], {'a': 4}]
print(deep_copied)  # [1, [200, 3], {'a': 400}]

2.4 特殊情况

2.4.1 不可变类型

# 元组的特殊情况
t1 = (1, 2, [3, 4])
t2 = copy.deepcopy(t1)

# 可以修改元组中的可变对象
t2[2][0] = 300
print(t1)  # (1, 2, [3, 4])
print(t2)  # (1, 2, [300, 4])

2.4.2 字典的拷贝

# 字典的内置copy方法(浅拷贝)
dict1 = {'a': [1, 2], 'b': 3}
dict2 = dict1.copy()

dict2['a'][0] = 100
print(dict1)  # {'a': [100, 2], 'b': 3}
print(dict2)  # {'a': [100, 2], 'b': 3}

3. 进制与位运算

3.1 进制转换

# 十进制转其他进制
num = 42
print(bin(num))  # 0b101010 (二进制)
print(oct(num))  # 0o52 (八进制)
print(hex(num))  # 0x2a (十六进制)

# 其他进制转十进制
print(int('101010', 2))  # 42
print(int('52', 8))      # 42
print(int('2a', 16))     # 42

3.2 位运算操作

x = 60  # 0011 1100
y = 13  # 0000 1101

# 按位与
print(x & y)   # 12 (0000 1100)

# 按位或
print(x | y)   # 61 (0011 1101)

# 按位异或
print(x ^ y)   # 49 (0011 0001)

# 按位取反
print(~x)      # -61

# 左移右移
print(x << 2)  # 240 (1111 0000)
print(x >> 2)  # 15  (0000 1111)

4. 作用域与命名空间

4.1 命名空间类型

  1. 局部命名空间(Local)
  2. 嵌套函数命名空间(Enclosing)
  3. 全局命名空间(Global)
  4. 内置命名空间(Built-in)

4.2 作用域查找顺序(LEGB规则)

# LEGB示例
x = 'global'

def outer():
    x = 'enclosing'
    
    def inner():
        x = 'local'
        print(x)  # 输出 'local'
    
    inner()
    print(x)      # 输出 'enclosing'

outer()
print(x)          # 输出 'global'

4.3 globals()和locals()

# globals()示例
global_var = 100

def test_function():
    local_var = 200
    print(globals())  # 显示全局变量字典
    print(locals())   # 显示局部变量字典

test_function()

4.4 变量访问限制

# 私有化示例
class MyClass:
    def __init__(self):
        self.public = "公有变量"
        self._protected = "保护变量"
        self.__private = "私有变量"

    def get_private(self):
        return self.__private

obj = MyClass()
print(obj.public)      # 正常访问
print(obj._protected)  # 可以访问,但不推荐
# print(obj.__private) # 报错
print(obj.get_private())  # 通过方法访问私有变量

4.5 property属性

class Person:
    def __init__(self):
        self.__age = 0

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, value):
        if 0 <= value <= 150:
            self.__age = value
        else:
            raise ValueError("Age must be between 0 and 150")

person = Person()
person.age = 25  # 使用setter
print(person.age)  # 使用getter