私有属性和私有方法

  • 1、通常我们约定,两个下划线(__)开头的属性是私有的(private)。其他为公共的(public);
  • 2、类内部可以访问私有属性(方法);
  • 3、类外部不能直接访问私有属性(方法);
  • 4、类外部可以通过 ”类名_私有属性(方法)名“ 访问私有属性(方法)

例程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Demo:
__price = 25.8

def __init__(self, u_name, u_age):
self.uname = u_name
self.__uage = u_age

def __age(self):
print("这是私有方法")
print("调用共有属性:", self.uname)
print("调用私有属性:", self.__uage)
print("调用私有类属性:", self.__price)

def name(self):
print("这是公有方法")
print("调用共有属性:", self.uname)
print("调用私有属性:", self.__uage)
print("调用私有类属性:", self.__price)
d = Demo("Liu",20)

执行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 调用共有方法
d.name
"""
这是公有方法
调用共有属性: Tom
调用私有属性: 18
调用私有类属性: 25.8
"""

# 调用私有方法(错误示范)
d.__age()
"""
Traceback (most recent call last):
File "D:/Local/PycharmProjects/private_obj/demo.py", line 32, in <module>
d.__age()
AttributeError: 'Demo' object has no attribute '__age'
"""

# 调用私有方法(正确示例)
d._Demo__age()
d._Demo__
"""
这是私有方法
调用共有属性: Tom
调用私有属性: 18
调用私有类属性: 25.8
"""

# 调用私有属性
print(Demo._Demo__price) # 25.8
print(d._Demo__uage) # 18

方法本质上也是属性!只不过是可以通过()执行而已。

因此私有方法的调用和私有属性的调用基本一样。

单继承和多继承

用不用super.__init__()方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class base_class:
def __init__(self,A):
self.feature_A=A
print("父类的构造函数")
print('属性A:',self.feature_A)


class son_class1(base_class):
def __init__(self,A):
base_class.__init__(self,A)

class son_class2(base_class):
def __init__(self,A):
super().__init__(A)

son1=son_class1(1)
son2=son_class2(2)

这两个继承的案例中,一个用了super().init,一个没用,效果相同,请问有什么区别?

下面是质谱清言的回答:

在Python中,super() 函数是用来调用父类(超类或基类)的一个方法的。在您的例子中,son_class1son_class2 都正确地调用了 base_class 的构造函数,但是它们使用的方法略有不同:

  1. son_class1 使用了直接父类名称来调用构造函数:base_class.__init__(self, A)。这种方法是明确的,它直接指明了要调用的基类。这在单继承的情况下工作得很好,但如果涉及到多继承,这种方法可能会导致一些问题,因为它不会考虑方法解析顺序(MRO),可能会导致一些父类的方法没有被正确调用。
  2. son_class2 使用了 super() 函数:super().__init__(A)super() 在这里会自动找到 son_class2 在MRO中的下一个类,并调用它的 __init__ 方法。这种方法在单继承和多继承中都能正确地工作,因为它自动遵循MRO。super() 的使用也是Python风格指南推荐的。
    以下是两种方法的主要区别:
  • 多继承中的兼容性super() 在多继承中可以正确地处理方法调用顺序,遵循MRO,确保每个父类的方法只会被调用一次。而直接使用父类名称的方法在多继承中可能会导致某个父类的方法被多次调用或者完全不被调用。
  • 代码的可维护性:使用 super() 可以让代码更加简洁,并且在未来如果类的继承关系发生变化时,使用 super() 的代码通常不需要修改。
  • 参数传递:在使用 super() 时,不需要显式地传递 self 参数,因为 super() 在当前类的上下文中工作,自动处理了 self
    在实践中,推荐使用 super(),因为它更符合Python的设计哲学,且在复杂继承结构中更加可靠。在单继承的情况下,两种方法都可以正常工作,但在多继承的情况下,使用 super() 会是更好的选择。
  • 推荐使用super()方法,该方法不需要传递self!

  • super()方法还可以继承其他的函数,都是一样的,并非只有构造函数。

  • 例程:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    # 父类1
    class base_class1:
    def __init__(self,A):
    self.feature_A=A
    print("父类1的构造函数被调用")
    print('父类1的属性A:',self.feature_A)
    def fun(self):
    print("父类1的函数被调用")
    # 父类2
    class base_class2:
    def __init__(self,A):
    self.feature_A=A
    print("父类2的构造函数被调用")
    print('父类2的属性A:',self.feature_A)
    def fun(self):
    print("父类2的函数被调用")
    # 子类1,继承自父类1

    class son_class1(base_class1):
    def __init__(self,A):
    base_class1.__init__(self,A)

    # 子类2,继承自父类1

    class son_class2(base_class1):
    def __init__(self,A):
    super().__init__(A)

    print("----------单继承(直接父类名称)------------")
    son1=son_class1(1)
    print("----------单继承(使用super() 函数)------------")
    son2=son_class2(2)

    # 多继承

    print("----------多继承(使用super() 函数)------------")

    # 子类3,继承自父类1和父类2

    class son_class3(base_class2,base_class1):
    def __init__(self,A):
    super().__init__(A) # super方法不需要传递self参数
    def fun(self):
    super().fun()

    print("构造函数的继承:",end='')
    son3 = son_class3(3)
    print("其他函数的继承:",end='')
    son3.fun()

其他的知识:

init方法和 new方法

他们会在类实例化的时候自动调用,并先调用new方法,再调用Init方法。

dir函数

  • dir() 是一个内置函数,用于列出对象的所有属性及方法。在 Python 中,一切皆对象

  • 如果 dir() 没有参数,则返回当前作用域中的名称列表

isinstance()函数

内置方法 isinstance(obj, class) 用来判断一个对象是否是某个类的实例。

object类

object 是所有类的基类(Base Class,也被称为超类(Super Class)或父类),如果一个类在定义中没有明确定义继承的基类,那么默认就会继承 object。

参考资料