Python进阶之路 8.2.2 方法和私有化

版权声明:本教程只限学习交流,不得用于商业用途。 https://blog.csdn.net/weixin_45086637/article/details/90933477

8.2.2 方法和私有化

Python类默认情况下,所有的方法都可以被外部访问。不过像很多其他编程语言,如Java、C#等,都提供了private关键字将方法私有化,也就是说只有类的内部方法才能访问私有化的方法,通过正常的方式是无法访问对象的私有化方法的(除非使用反射技术)。不过在Python类中并没有提供private或类似的关键字将方法私有化,但可以迂回解决。

在Python类的方法名前面加双下划线(__)可以让该方法在外部不可访问。

class person:
    # method1方法在类的外部可以访问

    def method1(self):
        print('method1')

    # __method2方法在类的外部不可访问

    def __method2(self):
        print('method2')


p = person()
p.method1()
# p.__method2()   # 抛出异常

输出结果:

method1

其实"__method2"方法也不是绝对不可访问。Python编译器在编译Python源代码时并没有将"__method2"方法真正私有化,而是一旦遇到方法名以双下划线(__)开头的方法,就会将方法名改成"_ClassName__methodName"的形式。其中ClassName表示该方法所在的类名,"__methodName"表示方法名。ClassName前面要加上单下划线(_)前缀。

对于上面的代码,Python编译器会将"__method2"方法更名为"_person__method2",所以在类的外部调用"__method2"方法会抛出异常。抛出异常的原因并不是"__method2"方法被私有化,而是Python编译器把"__method2"的名称改为"_person__method2"了。当了解了这些背后的原理,就可以通过调用"_person__method2"方法来执行"__method2"`方法。

class person:
    # method1方法在类的外部可以访问

    def method1(self):
        print('method1')

    # __method2方法在类的外部不可访问

    def __method2(self):
        print('method2')


p = person()
p.method1()
p._person__method2()    # 正常调用"__method2"方法

输出结果:

method1
method2

[例 8.2] 本例会创建一个MyClass类,并定义两个公共的方法(getName和setName)和一个私有的方法(__outName)。然后创建MyClass类的实例,并调用了这些方法。为了证明Python编译器在编译MyClass类时做了手脚,本例还使用了inspect模块中的getmembers函数获取MyClass类中所有的成员方法,并输出方法名。很显然"__outName"被改成了"_MyClass__outName"

class MyClass:

    # 公共方法

    def getName(self):
        return self.name

    # 公共方法

    def setName(self,name):
        self.name = name

        # 在类的内部可以直接调用私有方法

        self.__outName()

    # 私有方法

    def __outName(self):
        print('Name = {}'.format(self.name))


myClass = MyClass()

# 导入inspect模块

import inspect

# 获取MyClass类中所有的方法

methods = inspect.getmembers(myClass,predicate = inspect.ismethod)
print(methods)

# 输出类方法的名称

for method in methods:
    print(method[0])

print('--------------------')
# 调用setName方法
myClass.setName('Bill')

# 调用getName方法
print(myClass.getName())

# 调用'__outName'方法,这里调用了改完名后的方法,所以可以正常运行
myClass._MyClass__outName()

# 抛出异常,因为"__outName"方法在MyCall类中不存在
# print(myclass.__outName())

输出结果:

[('_MyClass__outName', <bound method MyClass.__outName of <__main__.MyClass object at 0x106907c70>>), ('getName', <bound method MyClass.getName of <__main__.MyClass object at 0x106907c70>>), ('setName', <bound method MyClass.setName of <__main__.MyClass object at 0x106907c70>>)]
_MyClass__outName
getName
setName
--------------------
Name = Bill
Bill
Name = Bill

从getmembers函数列出的MyClass类方法的名字可以看出,"_MyClass__outName"被绑定到了"__outName"方法上,可以将"_MyClass__outName"看作"__outName"的另一个别名,一旦为某个方法起了别名,那么原来的名字在类外部就不可用了。MyClass类中的getName方法和setName方法的别名和原始方法名相同,所以在外部可以直接调用getName和setName方法。

猜你喜欢

转载自blog.csdn.net/weixin_45086637/article/details/90933477
今日推荐