2026/1/13 类 参数引用问题

9 阅读4分钟

针对昨天的疑惑,做一下以下学习笔记

==原问题:==

class Privileges:
    """定义权限的属性"""

    def __init__(self,privileges=['can add post','can delete post','can ban user']):
        self.privileges = privileges

    def show_privileges(self):
        """打印管理员的权限"""
        print("作为管理员,具有权限如下:")
        for i in self.privileges:
            print(f"\n{i}")    
    
    
    # **上述代码中,为什么不可以写成以下的:**
class Privileges:
    """定义权限的属性"""
    def __init__(self,privileges):
        self.privileges = ['can add post','can delete post','can ban user']

    def show_privileges(self):
        """打印管理员的权限"""
        print("作为管理员,具有权限如下:")
        for i in self.privileges:
            print(f"\n{i}")

==这两种写法在功能上是不同的,详细区别:==

两种写法的区别:

写法1(原代码):

class Privileges:

    def __init__(self, privileges=['can add post', 'can delete post', 'can ban user']):
        self.privileges = privileges

特点:允许用户在创建实例时传入自定义的权限列表

写法2:

class Privileges:

    def __init__(self, privileges):  # 这个参数完全没用!
        self.privileges = ['can add post', 'can delete post', 'can ban user']

问题privileges参数完全被忽略,无论传入什么都会用固定列表

实际使用对比:

# 测试两种写法
print("=== 写法1:使用默认参数 ===")
class Privileges1:
    def __init__(self, privileges=['can add post', 'can delete post', 'can ban user']):
        self.privileges = privileges
    
    def show(self):
        print(f"权限: {self.privileges}")

# 用法多样
p1_default = Privileges1()  # 使用默认权限
p1_custom = Privileges1(['can edit', 'can view'])  # 自定义权限
print("默认实例:", end=" "); p1_default.show()
print("自定义实例:", end=" "); p1_custom.show()

print("\n=== 写法2:忽略参数 ===")
class Privileges2:
    def __init__(self, privileges):  # 参数被忽略!
        self.privileges = ['can add post', 'can delete post', 'can ban user']  # 固定
    
    def show(self):
        print(f"权限: {self.privileges}")

# 必须传参数,但参数被忽略
# p2 = Privileges2()  # 会报错:缺少参数
p2 = Privileges2(['can edit', 'can view'])  # 传入的参数被忽略
print("实例(传入的参数被忽略):", end=" "); p2.show()

更好的实现方式:

版本1:最推荐的做法

class Privileges:
    """管理员权限类"""
    DEFAULT_PRIVILEGES = ['can add post', 'can delete post', 'can ban user']
    
    def __init__(self, privileges=None):
        """初始化权限
        参数:
            privileges: 权限列表,如果为None则使用默认权限
        """
        if privileges is None:
            self.privileges = self.DEFAULT_PRIVILEGES.copy()  # 使用副本
        else:
            self.privileges = privileges
    
    def show_privileges(self):
        """显示所有权限"""
        if not self.privileges:
            print("该用户没有任何特殊权限")
            return
        
        print("👑 管理员权限列表:")
        for i, privilege in enumerate(self.privileges, 1):
            print(f"  {i}. {privilege}")
    
    def add_privilege(self, privilege):
        """添加权限"""
        if privilege not in self.privileges:
            self.privileges.append(privilege)
            print(f"✅ 已添加权限: {privilege}")
        else:
            print(f"⚠️  权限 {privilege} 已存在")
    
    def remove_privilege(self, privilege):
        """移除权限"""
        if privilege in self.privileges:
            self.privileges.remove(privilege)
            print(f"✅ 已移除权限: {privilege}")
        else:
            print(f"❌ 权限 {privilege} 不存在")

# 测试
print("=== 测试权限类 ===")
admin1 = Privileges()  # 使用默认权限
print("管理员1(默认权限):")
admin1.show_privileges()

print("\n管理员2(自定义权限):")
admin2 = Privileges(['can edit posts', 'can manage users', 'can view reports'])
admin2.show_privileges()

print("\n添加新权限:")
admin1.add_privilege('can manage settings')
admin1.add_privilege('can add post')  # 尝试添加已存在的权限
admin1.show_privileges()

版本2:与Admin类结合

class Privileges:
    """权限管理"""
    def __init__(self, privileges=None):
        self.privileges = privileges or ['can add post', 'can delete post', 'can ban user']
    
    def show(self):
        print("拥有的权限:")
        for priv in self.privileges:
            print(f"  - {priv}")


class Admin:
    """管理员用户"""
    def __init__(self, username, email, privileges=None):
        self.username = username
        self.email = email
        self.privileges = Privileges(privileges)  # 组合
    
    def show_info(self):
        print(f"\n管理员: {self.username}")
        print(f"邮箱: {self.email}")
        self.privileges.show()


# 创建管理员
admin_john = Admin("john_doe", "john@example.com")
admin_jane = Admin("jane_smith", "jane@example.com", 
                   ['can manage system', 'can audit logs'])

admin_john.show_info()
admin_jane.show_info()

为什么写法2有问题?

# 写法2的问题
class Privileges:
    def __init__(self, privileges):  # 这个参数必须传
        # 但这里完全忽略了传入的privileges参数!
        self.privileges = ['固定的默认列表']  # 总是用这个
    
# 使用时:
p = Privileges(['用户传入的列表'])  # 用户传入了,但被忽略了
# 无论传入什么,都是固定的列表,这很令人困惑

最佳实践建议:

  1. 使用默认参数时小心可变对象

    # 危险:列表是可变对象
    def __init__(self, privileges=[]):  # ❌ 不要这样
    
    # 安全:使用None作为默认值
    def __init__(self, privileges=None):  # ✅
        if privileges is None:
            privileges = ['默认1', '默认2']
    
  2. 明确参数用途

    # 好的:参数被实际使用
    def __init__(self, privileges=None):
        self.privileges = privileges or self.DEFAULT_PRIVILEGES
    
    # 不好的:参数被忽略
    def __init__(self, privileges):  # 参数没用
        self.privileges = ['固定列表']  # 总是这个
    
  3. 提供清晰的文档

    class Privileges:
        """
        权限管理类
    
        参数:
            privileges: 权限列表,可选。如果不提供则使用默认权限
        """
    

结论:

原写法更好,因为它:

  1. 允许用户自定义权限

  2. 提供了合理的默认值

  3. 参数被实际使用

而第二种写法中,privileges参数完全被浪费了,这让使用者困惑。