Kayle(入门编程 2025-07-16 18:18 采纳率: 100%
浏览 20
已结题

python,建立和访问私有属性

问题遇到的现象和发生背景

我在访问类的私有属性时报错,缺少一个位置参数self

class Person:
    __age = 18
    def get_age(self):
        return self.__age
p1 = Person
print(p1.get_age())

以下是报错信息

Traceback (most recent call last):
  File "D:\新建文件夹\tmp\123.py", line 789, in <module>
    print(p1.get_age())
          ~~~~~~~~~~^^
TypeError: Person.get_age() missing 1 required positional argument: 'self'

操作环境、软件版本等信息

python3.13

尝试过的解决方法

我在访问私有属性时,在调用的方法中加入self,但依然报错,显示我的self未定义

class Person:
    __age = 18
    def get_age(self):
        return self.__age
p1 = Person
print(p1.get_age(self))

最后根据教程修改成功

class Person:
    def __init__(self,age):
        self.__age = age
    def get_age(self):
        return self.__age
p1 = Person(18)
print(p1.get_age())

我想要达到的结果

我想清楚我最开始错误的地方,以及第一次尝试加入self为何也是错误的

  • 写回答

8条回答 默认 最新

  • .摘星. 优质创作者: 人工智能技术领域 2025-07-17 01:34
    关注

    摘星参考千问来帮您回答这个问题!

    你提出的问题非常具有代表性,是许多 Python 初学者在学习类和对象时经常遇到的典型错误。下面我将从以下几个方面进行详细分析:


    一、问题现象回顾

    你写的代码如下:

    class Person:
        __age = 18
        def get_age(self):
            return self.__age
    
    p1 = Person
    print(p1.get_age())
    

    运行后报错:

    TypeError: Person.get_age() missing 1 required positional argument: 'self'
    

    二、错误原因分析

    1. Person 是类,不是实例

    p1 = Person
    

    这行代码没有创建 Person 类的实例,只是将 Person 这个类赋值给了变量 p1

    也就是说,p1 指向的是类本身(Person),而不是一个对象实例。

    所以当你调用 p1.get_age() 时,实际上是调用了类方法,而 get_age 是一个实例方法,它需要一个隐式的 self 参数(即对象实例)来调用。


    2. __age 是类属性还是实例属性?

    在你的代码中:

    class Person:
        __age = 18
    

    这是一个类属性(也叫静态属性),而不是实例属性。因为没有使用 self 来赋值,而是直接在类中定义。

    虽然 __age 是私有属性(通过双下划线 _ 实现名称改写),但它仍然是类级别的属性,而不是每个实例独有的。

    但是,在 get_age 方法中,你写的是:

    return self.__age
    

    这里假设 __age 是实例属性,但事实上它是一个类属性,因此在调用 self.__age 时,Python 会尝试查找实例的 __age 属性,而这个属性并不存在,导致错误。

    注意: 在 Python 中,类属性和实例属性是不同的概念。类属性属于类本身,而实例属性属于对象实例。


    3. 为什么加入 self 也会报错?

    你尝试了这样写:

    print(p1.get_age(self))
    

    这行代码试图显式传入 self,但实际上 p1 是类本身(Person),不是对象实例。所以 self 并未被定义,导致 NameError 或其他错误。


    三、正确做法与解释

    正确的做法是创建对象实例:

    p1 = Person()
    print(p1.get_age())
    

    这时 p1Person 的一个实例,get_age() 是一个实例方法,Python 会自动将 p1 作为 self 参数传递进去。


    四、类属性 vs 实例属性的区别

    类型定义位置访问方式示例
    类属性类内部类名.属性self.属性Person.__ageself.__age
    实例属性__init__ 方法中self.属性self.__age = age

    五、你最终成功修改的版本

    class Person:
        def __init__(self, age):
            self.__age = age
    
        def get_age(self):
            return self.__age
    
    p1 = Person(18)
    print(p1.get_age())  # 输出 18
    

    在这个版本中:

    • __init__ 是构造函数,用于初始化实例属性。
    • self.__age 是实例属性。
    • p1 = Person(18) 创建了一个 Person 实例。
    • p1.get_age() 调用实例方法,self 由 Python 自动传入。

    六、关于私有属性的访问限制

    在 Python 中,使用双下划线 __ 前缀会使属性“伪装”为私有属性,但并不是真正的不可访问。Python 会对这些属性进行名称改写,例如:

    class Person:
        __age = 18
    

    实际上等价于:

    class Person:
        _Person__age = 18
    

    因此你可以这样访问:

    p = Person()
    print(p._Person__age)  # 可以访问,但不推荐
    

    但为了封装性,建议使用 getter 和 setter 方法来访问私有属性。


    七、总结:你最初错误的原因

    错误点原因
    p1 = Person没有创建对象实例,只是引用了类
    print(p1.get_age())调用的是类方法,缺少 self
    print(p1.get_age(self))self 未定义,且 p1 不是实例
    __age 是类属性,但 get_age 使用 self.__age导致找不到实例属性,引发错误

    八、完整示例对比

    ❌ 错误示例(你最初的代码)

    class Person:
        __age = 18
        def get_age(self):
            return self.__age
    
    p1 = Person
    print(p1.get_age())  # 报错:missing 1 required positional argument: 'self'
    

    ✅ 正确示例(创建实例)

    class Person:
        def __init__(self, age):
            self.__age = age
    
        def get_age(self):
            return self.__age
    
    p1 = Person(18)
    print(p1.get_age())  # 输出 18
    

    九、扩展知识:类方法 vs 实例方法

    方法类型定义方式是否需要 self示例
    实例方法def method(self):✅ 需要def get_age(self):
    类方法@classmethod def m(cls):✅ 需要(参数为 cls@classmethod def from_age(cls, age):
    静态方法@staticmethod def m():❌ 不需要@staticmethod def say_hello():

    十、最后建议

    • 总是使用 self 来访问实例属性
    • 不要混淆类属性和实例属性
    • 创建对象实例后再调用实例方法
    • 了解 Python 的名称改写机制(name mangling)

    如果你还有其他疑问,比如如何访问类属性、如何设计更复杂的类结构,欢迎继续提问!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(7条)

报告相同问题?

问题事件

  • 系统已结题 7月25日
  • 已采纳回答 7月17日
  • 创建了问题 7月16日