Python中的方法说明

Python类中方法包含共有、私有、保护方法,还包含魔术方法。

private (私有) 属性/方法名

  1. __xxx "双下划线"开头
  2. Python并没有真正的私有化支持,但可用双下划线得到伪私有
  3. 只有类对象自己能访问,连子类对象也不能访问到这个数据。

方法或者变量是private类型时,其方法或者变量实际上是被转换了。在内部,python使用一种 name mangling 技术(名字重整:目的是防止子类意外重写基类的方法或者属性1),转换规则是在变量XXX的前插入类名,在类名前加一个下划线"_",形成"_ClassName__XXX"2

class ClassDef(object):
    def __init__(self):
        # public
        self.name = "class_def"
        # private
        self.__age = 29
        # protected
        self._sex = "man"

    def fun1(self):
        print("call public function")

    def __fun2(self):
        print("call private function")

    def _fun3(self):
        print("call protected function")
        
    def print_age(self):
        print(self.__age)
        
        
if __name__ == "__main__":
    # 实例化类对象
    class_def = ClassDef()
# 调用public
>>> class_def.fun1()
"call public function"
>>> print(class_def.name)
"class_def"

# 调用protect
>>> class_def._fun3()
"call private function"
>>> print(class_def._sex)
"man"

# 调用private
>>> class_def._ClassDef__fun2()
"call private function"
>>> print(class_def._ClassDef__age)
29

# 以下调用private会报错
>>> class_def.__fun2()
"Traceback (most recent call last):
  File "XXX.py", line 39, in <module>
    class_def.__fun2()
AttributeError: 'ClassDef' object has no attribute '__fun2'"
>>> print(class_def.__age)
"Traceback (most recent call last):
  File "XXX.py", line 39, in <module>
    print(class_def.__age)
AttributeError: 'ClassDef' object has no attribute '__age'"

可见private是被转换了,不可直接调用。但可以通过赋值后使用。

# 以下调用private不会报错
>>> class_def.__age = 80
>>> print(class_def.__age)
80
>>> class_def.print_age()
29 # 可以看到类的私有属性并没有被真正修改
>>> class_def._ClassDef__age = 70
>>> class_def.print_age()
70

如果不给class_def.__age赋值,直接打印会触发AttributeError错误。**给class_def.__age赋值的操作,其实是在class_def中定义了一个名为__age的变量(因为Python中的都是动态变量)。**类中真正的属性class_def._ClassDef__age是没有被更改的。3

protect (保护) 属性/方法

  1. _xxx “单下划线”开头
  2. 只有类对象(即类实例)和子类对象自己能访问到这些变量
  3. 不能用from module import *导入。需通过类提供的接口进行访问。

public (共有) 属性/方法

  1. xxx 不以下划线开头。
  2. Python中数据和方法默认都是pubic类型。
  3. public类型可以被子类、类内以及类外访问。

魔术方法

在Python中,所有以"__“双下划线包起来的方法,都统称为"Magic Method”,中文称『魔术方法』,例如类的初始化方法 __init__()。4

  1. __xxx__ 系统定义名字,前后均有一个"双下划线"
  2. 可以给类增加"magic"的特殊方法,如 __init__() 代表类的构造函数。
  3. 从使用范围来说,__init__()可以被继承,也可以直接调用。
魔术方法含义
__new__(cls, […])在一个对象实例化的时候所调用的第一个方法。第一个参数是这个类,其他的参数是用来直接传递给 __init__ 方法。5
__init__(self, […])构造器。构造函数被调用的时候的任何参数都将会传给它。(比如如果我们调用 x = SomeClass(10, 'foo'),那么 __init__ 将会得到两个参数10和foo。)
__del__(self)析构器。它定义的是当一个对象进行垃圾回收时候的行为。它不实现语句 del x
Python的垃圾回收机制——__del__()析构器
s = '123'
print('del...running')
del s

当用del删除一个对象时,其实并没有直接清除该对象的内存空间。Python 采用’引用计数’ 的算法方式来处理回收,即:当某个对象在其作用域内不再被其他对象引用的时候,Python 就自动清除对象。

而析构函数 __del__()在引用的时候就会自动清除被删除对象的内存空间。6
  
  在对象的生命周期结束时,__del__会被调用,可以将__del__理解为"析构函数"。__del__定义的是当一个对象进行垃圾回收时候的行为。

有一点容易被人误解,实际上,x.__del__()并不是对于del x的实现,但是往往执行del x时会调用x.__del__()7

class Foo(object):
    def __init__(self):
       print('foo __init__')
       return None  # 必须返回None,否则抛TypeError

    def __del__(self):
        print('foo __del__')
# 实例化类对象
>>> foo = Foo()
"foo __init__"
"foo __del__"
>>> foo.__del__()
"foo __del__"
>>> print(foo)
"<__main__.Foo object at 0x7fc3669b7250>"
>>> del foo
# 打印会报错
>>> print(foo)
"NameError: name 'foo' is not defined"

参考文档


  1. Python 类的私有化 ↩︎

  2. python类私有属性的坑-真假的私有属性 ↩︎

  3. Python:为什么类中的私有属性可以在外部赋值并访问? ↩︎

  4. Python中的魔术方法详解 ↩︎

  5. Python 魔术方法指南-构造和初始化 ↩︎

  6. python析构函数 ↩︎

  7. 介绍Python的魔术方法 - Magic Method ↩︎

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值