類&成員可見性&繼承

七月_M發表於2020-12-05

類名定義:

  • 第一個字母大寫
  • 多個單詞時,使用駝峰式,如StudentHomework

Tips:

現實世界事務的特徵和行為,抽象到類就是資料成員和方法。

例項化物件時,會自動呼叫__init__()函式。

self: 當前呼叫該方法的物件。

變數

例項變數

python 在__init__函式內定義例項變數。

嘗試訪問一個例項變數時,python首先會在物件的例項變數列表查詢,如果找不到,則到類變數列表尋找,如果還找不到,則到其父類中尋找。

  • __dict__儲存了物件/類的屬性。
student = Student('娜可露露',23)

print(student.__dict__)
print(Student.__dict__)

#執行結果
> python p\p2.py
{'name': '娜可露露', 'age': 23}
PS E:\word\Python\code\abc> python p\p2.py
{'name': '娜可露露', 'age': 23}
{'__module__': '__main__', 'sum': 1, '__init__': <function Student.__init__ at 0x0000023C61AFDF70>, 'print_file': <function Student.print_file at 0x0000023C61B04040>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

類變數

例項方法中訪問類變數:

  1. 類名.變數名
  2. self.__class__.變數名

class Student():
    num_sum = 0
    name = 'qiyue'
    def __init__(self,name,age):
        self.name = name
        self.age = age
        print(Student.num_sum)
        print(self.__class__.num_sum)


print(Student.num_sum)

方法

例項方法

通過類呼叫例項方法,需要傳一個引數給self形參,self此時就是一個普通引數。

class Student():
    num_sum = 0
    # name = 'qiyue'
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.__score = 0 

    def do_homework(self):
        print('day day up')


student = Student('娜可露露',23)
Student.do_homework(student)
Student.do_homework(1)

類方法

定義

    @classmethod
    def plus_sum(cls):
        pass

在類方法中操作類變數

class Student():
    num_sum = 0

    @classmethod
    def plus_sum(cls):
        cls.num_sum += 1
        print('當前學生總數為:',cls.num_sum)


Student.plus_sum() #通過類名呼叫類方法
student.plus_sum() #通過物件也可以呼叫類方法

類方法內部 不能訪問例項變數。

靜態方法

定義

    @staticmethod
    def add(x,y):
        pass

呼叫

類和物件都可以呼叫靜態方法。

student = Student('娜可露露',23)
Student.add(4,5)
student.add(2,3)

靜態方法內部可以訪問類變數。

class Student():
    num_sum = 0

    @staticmethod
    def add(x,y):
        print(Student.num_sum)

靜態方法內部不可以訪問例項變數。

Tips:

能用靜態方法的地方都可以用類方法來代替,當所定義函式跟類/物件沒太大關聯時使用靜態方法。

成員可見性

私有屬性/方法

在python中,一個變數/方法開頭是雙下劃線“__”,則認為該變數/方法是私有的。

前後都有雙下劃線,認為是公開的,比如__init__()。

class Student():       
    def __marking(self,score):
        pass

#呼叫會報錯
student = Student('娜可露露',23)
print(student.__marking(-1))
#執行結果
> python p\p2.py
Traceback (most recent call last):
  File "E:\word\Python\code\abc\p\p2.py", line 35, in <module>
    print(student.__marking(-1))
AttributeError: 'Student' object has no attribute '__marking'

仍然可以訪問私有屬性?

如果直接給私有屬性賦值/讀取,程式不會報錯。

class Student():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.__score = 0

student = Student('娜可露露',23)
student.__score = 100
print(student.__score)

原因是:由於python動態語言的特性,實際上是給物件新增加了一個屬性。

示例:

student = Student('娜可露露',23)
student2 = Student('橘子',20)
student.__score = 100
print(student.__score)
print(student.__dict__)
print(student2.__dict__)
print(student2.__score)

#執行結果
> python p\p2.py
100
{'name': '娜可露露', 'age': 23, '_Student__score': 0, '__score': 100}
{'name': '橘子', 'age': 20, '_Student__score': 0}
Traceback (most recent call last):
  File "E:\word\Python\code\abc\p\p2.py", line 43, in <module>
    print(student2.__score)
AttributeError: 'Student' object has no attribute '__score'

分析:

可以看到student物件的屬性包括'_Student__score'和 '__score',其中'_Student__score'是建構函式中定義的私有屬性(python自動改名),'__score'是後來動態新增的屬性。

而student2物件就不包括屬性'__score'。

因此還可以得出一個結論:不能動態新增私有屬性。

其實仍然可以訪問

可以通過改名後的屬性名來訪問該私有屬性。

student = Student('娜可露露',23)
student._Student__score = 99
print(student._Student__score)

執行結果:
> python p\p2.py
99

繼承

python支援多繼承。

呼叫父類構造方法

一種顯式呼叫父類建構函式的方法(一般不使用):

class Human():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.__score = 0

class Student(Human):
    def __init__(self,school,name,age):
        self.school = school
        Human.__init__(self,name,age) #呼叫父類構造方法

主流呼叫方式::

class Student(Human):

    def __init__(self,school,name,age):
        self.school = school

        super(Student,self).__init__(name,age)  

 

相關文章