1. 程式人生 > >day30 Pyhton 面向物件 繼承.裝飾器

day30 Pyhton 面向物件 繼承.裝飾器

一面向物件相關

談談你對面向物件的理解

  1.泛泛談:什麼情況下使用面向物件

  2.針對面向物件的 封裝 繼承 多型一個一個的談

  3.根據你工作中的實際情況對應來舉例子

封裝

1.廣義上:普遍的大家認為的封裝,就是把一類相同屬性和方法的事務抽象為一個類

  把屬性和方法封裝在一個類中

  是為了複雜的角色關係的程式中,能夠把屬於各個角色的方法分開

  使得程式碼更加簡潔 清晰(狗不能呼叫attack,人不能呼叫bite)

 狹義上:在類中,可以定義一些私有成員(靜態屬性,方法,物件的屬性)

    __私有的成員名,就定義為私有的了

    不能在類的外部使用,也不能被繼承,旨在保護類中的一些資訊

 應該知道

  為什麼私有的成員不能在類的外部直接使用?

    所有的私有成員,都是在建立的時候變異了,變成_類名__私有的成員名

  為什麼私有的成員可以直接在類的內部使用?

    在類的內部使用私有成員的時候,類會自動的在這些成員的前面加上_類名

  

  什麼情況下使用封裝:

    某一個屬性(靜態屬性\物件屬性):不想被檢視,不想被隨意修改(只能看,但是不能(隨意)改)

    某一個方法: 不想被外部呼叫

  不善於使用封裝的概念,分不清楚什麼情況下使用:

    最好能夠符合規範的開發

    即使沒有恰當的使用封裝,也不影響我們實現程式碼的功能

二.

子類不能繼承父類的私有方法

class Foo(object):
#     A = 123
#     __私有的靜態變數 = 'ABC'   # _Foo__私有的靜態變數
#     print('---> ',__私有的靜態變數) # 在類的內部使用  _Foo__私有的靜態變數
#
# class Son(Foo):
#     def func(self):
#         print('--> 1 ',Son.A) # 子類沒有找父類,能找到
#         print('--> 2 ',Foo.__私有的靜態變數) # 子類沒有找父類,找不到"_Son__私有的靜態變數"
type object 'Foo' has no attribute '_Son__私有的靜態變數'
#
# print(Foo.__私有的靜態變數) # Son().func()

子類的內部不能使用父類的私有方法

class Foo(object):
    def __func(self):    # self._Foo__func
        print('in foo')

class Son(Foo):
    def wahaha(self):
        self.__func()  # self._Son__func,不能在子類的內部使用父類的私有方法

s = Son()
s.wahaha()
class Foo(object):
    def __init__(self):
            self.__func()    # _Foo__func
            self.func()

    def __func(self):print('in Foo __func')  # _Foo__func

    def func(self):print('in Foo func')

class Son(Foo):
    def __func(self):print('in Son __func')   # _Son__func

    def func(self):print('in Son func')
Foo()._Foo__func()
Son()
# 呼叫私有的方法或者屬性
    # 不需要考慮self是誰的物件
    # 只要是私有的方法或者屬性,就一定是在呼叫的當前類中執行方法
# 當某個方法或者屬性,不希望被子類繼承的時候,也可以把這個方法\屬性定義成私有成員

三.三個裝飾器方法
@classmethod

@property

@staticmethod

class A:
    __count = 0   # 隱藏了count屬性
    def __init__(self,name):
        self.name = name
        self.__add_count()  # 每一次例項化的時候調
                            # 用私有方法來對__count進行累加
    @classmethod
    def __add_count(cls):  # 定義一個私有的方法
        # print(cls,A)
        cls.__count += 1      # 讓這個方法只能在類的內部被使用

    @classmethod  # 被classmethod裝飾器裝飾的方法,都有一個預設的引數,這個引數就是當前類
    def show_count(cls):   # 定義一個普通方法,
        # print(cls,A)
        return cls.__count    # 讓使用者可以從外部檢視__count的值

print(A.show_count())
alex = A('alex')
print(alex.show_count())
yuan = A('yuan')
print(A.show_count())

 

為什麼有類方法
# 有的時候,
# 在類中會有一種情況,就是這個方法並不需要使用某一個物件的屬性
# 因此 這個方法中的self引數是一個完全無用的引數
# show_count是一個檢視類中屬性的方法,這樣的方法和某一個物件並沒有直接聯絡

# 本質上 : 一個方法不用物件屬性但是使用靜態屬性 -- 類方法@classmethod
# 某一個方法被創造出來,就是為了進行對靜態變數進行操作
# 根本不涉及到物件
# 所以這個方法就應該被定義成 類方法(被@classmethod裝飾)
# 呼叫這個類方法,可以使用物件呼叫,也可以使用類呼叫
# 但是這個方法的預設引數永遠是當前類的名稱空間,而不是物件的

 

# 如果一個類中的方法不用物件屬性也不用靜態屬性 -- 靜態方法@staticmethod
# 那實際上這個方法就是一個普通的函式
class User(object):
    @staticmethod
    def login(arg1,arg2):   # 是User類中的名字 函式的名字 login就是一個類中的靜態方法,本質上就是一個函式
        print(arg1,arg2)
        return (arg1+arg2)
class Student(User):pass
class Manager(User):pass

ret = User.login(1,2)
print(ret)#3
a=Student.login(2,4)
print(a)#6
b=Manager.login(2,3)
print(b)#5
#               普通的方法               類方法                 靜態方法
# 預設引數        self                    cls                   無
# 操作的變數      操作物件的屬性          操作靜態屬性         既不操作物件屬性,也不操作類的屬性
# 所屬的名稱空間   類                       類                    類
# 呼叫方式        物件                   類/物件                類/物件
# 對應的裝飾器     無                   @classmethod        @staticmethod
# 用哪一個名稱空間中的名字,就定義不同的方法
# 只要用self 就是普通方法,只能用物件調
# 只要用cls  就是類方法,可以用類,可以用物件
# 啥也不用   就是靜態方法,可以用類,可以用物件

# 私有的
# 私有的普通方法
# 私有的類方法
# 私有的靜態方法

# 先定義類
# 寫方法
# 寫具體的方法中的程式碼
# 寫完之後,發現沒有用到self,那麼如果用到類,就定義成類方法,如果啥也沒用到,靜態方法

# 先定義函式
# 寫函式
# 寫具體函式中的程式碼
# 寫完之後,發現要挪進類裡,如果啥也沒用到,靜態方法;如果用到類,就定義成類方法