您好!此筆記的文本和代碼以網盤形式分享於文末!
因個人能力有限,錯誤處歡迎大家交流和指正!基礎部分內容簡單,但多且零散!
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
面向對象:
"""
"""
類(Class):
用來描述具有相同的屬性和方法的對象的集合。
它定義了該集合中每個對象所共有的屬性和方法。
對象是類的實例。
class 類名:
'類的文檔字符串'
類體
"""
# # 創建一個類
# class Data:
# pass
#
#
# class Person:
# role = 'person' # 角色屬性
#
# def walk(self): # 方法,動態屬性
# print("person is walking...")
#
#
# # 屬性的引用
# # 查看人的role屬性
# print(Person.role)
# # 引用人的走路方法,注意,這裏不是在調用
# print(Person.walk)
# # 實例化: 類名加括號就是實例化
# class Person:
# role = 'person' # 角色屬性
#
# def __init__(self, name):
# self.name = name
#
# def walk(self): # 方法,動態屬性
# print("person is walking...")
#
#
# # 實例化的過程就是類——>對象的過程 egg 爲對象
# # 語法:對象名 = 類名(參數)
# egg = Person('egon')
# # 查看對象的屬性和調用方法
# print(egg.name)
# egg.walk()
# print(egg.walk())
"""
class 類名:
def __init__(self,參數1,參數2):
self.對象的屬性1 = 參數1
self.對象的屬性2 = 參數2
def 方法名(self):pass
def 方法名2(self):pass
對象名 = 類名(1,2) #對象就是實例,代表一個具體的東西
#類名() : 類名+括號就是實例化一個類,相當於調用了__init__方法
#括號裏傳參數,參數不需要傳self,其他與init中的形參一一對應
#結果返回一個對象
對象名.對象的屬性1 #查看對象的屬性,直接用 對象名.屬性名 即可
對象名.方法名() #調用類中的方法,直接用 對象名.方法名() 即可
"""
# # 創建一個狗類
# class Dog:
# role = 'dog'
#
# def __init__(self, name, breed, aggressivity, life_value):
# self.name = name # 每一隻狗都有自己的暱稱;
# self.breed = breed # 每一隻狗都有自己的品種;
# self.aggressivity = aggressivity # 每一隻狗都有自己的攻擊力;
# self.life_value = life_value # 每一隻狗都有自己的生命值;
#
# def attack(self, animal):
# # 狗被攻擊,狗的生命值會下降
# animal.life_value -= self.aggressivity
#
#
# # 實例化二哈
# ha1 = Dog('大二哈', '哈士奇', 10, 1000)
# ha2 = Dog('小二哈', '哈士奇', 7, 800)
# # 交互
# print(ha1.life_value)
# print(ha2.life_value)
#
# ha1.attack(ha2)
# ha2.attack(ha1)
#
# print(ha1.life_value)
# print(ha2.life_value)
# # 計算圓的周長和麪積
# from math import pi
#
#
# class Circle:
# """
# 定義了一個圓形類;
# 提供計算面積(area)和周長(perimeter)的方法
#
# """
# # 圓的半徑
# def __init__(self, radius):
# self.radius = radius
#
# def area(self):
# return pi * self.radius * self.radius
#
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# # 實例化一個圓
# circle = Circle(10)
# # 計算對象圓的面積
# area1 = circle.area()
# # 計算對象圓的周長
# per1 = circle.perimeter()
# # 打印圓面積和周長
# print(area1, per1)
"""
創建一個類就會創建一個類的名稱空間
類的靜態屬性和動態屬性:
靜態屬性就是直接在類中定義的變量
動態屬性就是定義在類中的方法
類的數據屬性是共享給所有對象的,地址相同
類的動態屬性是綁定到所有對象的,地址不同
"""
# # 類的組合指的是,在一個類中以另外一個類的對象作爲數據屬性
# class Weapon:
# # 這是該裝備的主動技能
# def prick(self, obj):
# obj.life_value -= 500
#
#
# class Person:
# role = 'person'
#
# def __init__(self, name):
# self.name = name
# # 給角色綁定一個武器;Weapon實例化爲Person的一個屬性
# self.weapon = Weapon()
#
#
# egg = Person('egon')
# # 直接egg.weapon來使用組合類中的所有方法
# egg.weapon.prick()
# # 圓環的面積周長的組合類
# from math import pi
#
#
# class Circle:
# """
# 定義了一個圓形類;
# 提供計算面積(area)和周長(perimeter)的方法
# """
# def __init__(self, radius):
# self.radius = radius
#
# def area(self):
# return pi * self.radius * self.radius
#
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# class Ring:
# """
# 定義了一個圓環類
# 提供圓環的面積和周長的方法
# """
# def __init__(self, radius_outside, radius_inside):
# self.outside_circle = Circle(radius_outside)
# self.inside_circle = Circle(radius_inside)
#
# def area(self):
# return self.outside_circle.area() - self.inside_circle.area()
#
# def perimeter(self):
# return self.outside_circle.perimeter() + self.inside_circle.perimeter()
#
#
# ring = Ring(10, 5)
# # 計算環形的周長
# print(ring.perimeter())
# # 計算環形的面積
# print(ring.area())
# # 類與組合的類之間的關係,它是一種“有”關係
# # 當類之間有顯著不同,且較小的類是較大的類所需要的組件
# class BirthDate:
# """
# 關於生日信息的類,年月日
# """
# def __init__(self, year, month, day):
# self.year = year
# self.month = month
# self.day = day
#
#
# class Couse:
# """
# 課程信息的類,名稱價格週期
# """
# def __init__(self, name, price, period):
# self.name = name
# self.price = price
# self.period = period
#
#
# class Teacher:
# """
# 教師信息的類,姓名性別生日授課
# """
# def __init__(self, name, gender, birth, course):
# self.name = name
# self.gender = gender
# self.birth = birth
# self.course = course
#
# def teach(self):
# print('teaching')
#
#
# t1 = Teacher('egon', 'male',
# BirthDate('1995', '1', '27'),
# Couse('python', '28000', '4 months')
# )
#
# print(t1.birth.year, t1.birth.month, t1.birth.day)
# print(t1.course.name, t1.course.price, t1.course.period)
# print(t1.birth)
# # 人狗大戰
# class Person:
# """
# 定義一個人的類, 姓名攻擊力生命值金錢
# """
# role = 'person'
#
# def __init__(self, name, aggressivity, life_value, money):
# self.name = name
# self.aggressivity = aggressivity
# self.life_value = life_value
# self.money = money
#
# def attack(self, dog):
# """
# 定義了人的一個攻擊的方法
# """
# dog.life_value -= self.aggressivity
#
#
# class Dog:
# """
# 定義一個狗的類,暱稱品種攻擊力生命值
# """
# role = 'dog' # 狗的角色屬性都是狗
#
# def __init__(self, name, breed, aggressivity, life_value):
# self.name = name
# self.breed = breed
# self.aggressivity = aggressivity
# self.life_value = life_value
#
# def bite(self, people):
# """
# 定義了一個攻擊方法
# """
# people.life_value -= self.aggressivity
#
#
# class Weapon:
# """
# 定義了一個武器,名稱價格攻擊附加耐久值
# """
# def __init__(self, name, price, aggrev, life_value):
# self.name = name
# self.price = price
# self.aggrev = aggrev
# self.life_value = life_value
#
# def update(self, obj):
# """
# 定義使用武器附加的方法
# """
# obj.money -= self.price
# obj.aggressivity += self.aggrev
# obj.life_value += self.life_value
#
# def prick(self, obj):
# """
# 定義一個攻擊技能的方法
# """
# obj.life_value -= 500
#
#
# # 實例化武器、狗、人
# lance = Weapon('長矛', 200, 6, 100)
# egg = Person('egon', 10, 1000, 600)
# ha2 = Dog('大哈', '哈士奇', 10, 1000)
#
# # 購置裝備
# if egg.money > lance.price:
# lance.update(egg)
# egg.weapon = lance
#
# print(egg.money, egg.life_value, egg.aggressivity)
#
# print(ha2.life_value)
# # 這裏自帶了武器的攻擊附加傷害
# egg.attack(ha2)
# print(ha2.life_value)
# # 發動武器技能加成
# egg.weapon.prick(ha2)
# print(ha2.life_value)
# # 類的繼承
# # 定義父類1
# class ParentClass1:
# pass
#
#
# # 定義父類2
# class ParentClass2:
# pass
#
#
# # 單繼承
# # 基類是ParentClass1,派生類是SubClass
# class SubClass1(ParentClass1):
# pass
#
#
# # python支持多繼承,用逗號分隔開多個繼承的類
# class SubClass2(ParentClass1, ParentClass2):
# pass
#
#
# print(SubClass1.__bases__)
# print(SubClass2.__bases__)
# # 無指定基類,默認繼承object類,其是所有python類的基類
# print(ParentClass1.__bases__)
# # 抽象:即抽取類似或者說比較像的部分。
# # 繼承是基於抽象的結果,通過繼承的方式表達出抽象的結構
# # 將奧巴馬和梅西這倆對象比較像的部分抽取成類;
# # 將人,豬,狗這三個類比較像的部分抽取成父類。
# # 抽象是分析過程,繼承是實現方式
# class Animal:
#
# def eat(self):
# print("%s 喫 " % self.name)
#
# def drink(self):
# print("%s 喝 " % self.name)
#
#
# class Cat(Animal):
#
# def __init__(self, name):
# self.name = name
# self.breed = '貓'
#
# def climb(self):
# print('爬樹')
#
#
# class Dog(Animal):
#
# def __init__(self, name):
# self.name = name
# self.breed = '狗'
#
# def look_after_house(self):
# print("%s " '汪汪叫' % self.name)
#
#
# c1 = Cat('小白貓')
# c1.eat()
#
# d1 = Dog('大金毛')
# d1.drink()
#
# d2 = Dog('帥邊牧')
# d2.look_after_house()
# # 派生,子類可添加新的屬性或重新定義這些屬性
# # 重新定義的屬性不會影響到父類
# class A:
# def hahaha(self):
# print('A')
#
#
# class B(A):
# def hahaha(self):
# super().hahaha()
# print('B')
#
#
# class C(A):
# def hahaha(self):
# print('C')
#
#
# class D(A):
# def hahaha(self):
# print('D')
#
# def newmethod(self):
# print("派生,新屬性")
#
#
# a = A()
# b = B()
# c = C()
# d = D()
# a.hahaha()
# print("---***---")
# b.hahaha()
# print("---***---")
# c.hahaha()
# print("---***---")
# super(B, b).hahaha()
# print("---***---")
# d.hahaha()
# d.newmethod()
# 接口類,借用abc模塊來實現接口
# 接口繼承實質上是要求“做出一個良好的抽象,
# 這個抽象規定了一個兼容接口,
# 使得外部調用者無需關心具體細節,
# 可一視同仁的處理實現了特定接口的所有對象”
# ——這在程序設計上,叫做歸一化。
# 歸一化,讓使用者無需關心對象的類是什麼,
# 只需要的知道這些對象都具備某些功能
# # 抽象類是一個特殊的類,它的特殊之處在於只能被繼承,不能被實例化
# # 子類必須實現抽象方法
# # 需要藉助模塊abc來實現
# import abc
#
#
# class All_file(metaclass=abc.ABCMeta):
# all_type = 'file'
#
# @abc.abstractmethod # 定義抽象方法,無需實現功能
# def read(self):
# # 子類必須定義讀功能
# pass
#
# @abc.abstractmethod
# def write(self):
# # 子類必須定義些功能
# pass
#
#
# # 子類繼承抽象類,但是必須定義read和write方法
# class Txt(All_file):
# def read(self):
# print('文本數據的讀取方法')
#
# def write(self):
# print('文本數據的寫入方法')
#
#
# # 子類繼承抽象類,但是必須定義read和write方法
# class Process(All_file):
# def read(self):
# print('進程數據的讀取方法')
#
# def write(self):
# print('進程數據的寫入方法')
#
#
# wenbenwenjian = Txt()
# jinchengwenjian = Process()
#
# # 這樣都是被歸一化了,也就是一切皆文件的思想
# wenbenwenjian.read()
# jinchengwenjian.write()
#
# print(wenbenwenjian.all_type)
# print(jinchengwenjian.all_type)
# 抽象類的本質還是類,指的是一組類的相似性包括數據屬性和函數屬性
# 接口強調函數屬性的相似性
# 抽象類是一個介於類和接口直接的一個概念,
# 同時具備類和接口的部分特性,可以用來實現歸一化設計
# 繼承抽象類的過程中,我們應該儘量避免多繼承;
# 繼承接口的時候,我們反而鼓勵你來多繼承接口
# 接口隔離原則:使用多個專門的接口,而不使用單一的總接口。
# 即客戶端不應該依賴那些不需要的接口。
"""
繼承順序 深度優先和廣度優先
經典類:C1 和 C2 都是經典類
class C1:
pass
class C2:
pass
新式類: N1 和 N2都是新式類
class N1(object):
pass
class N2(N1):
pass
類是經典類時,多繼承的情況下,會按照深度優先方式查找
類是新式類時,多繼承情況下,會按照廣度優先的方式查找
python3中統一都是新式類
python2中才分新式類與經典類
"""
# class A(object):
# def test(self):
# print('from A')
#
#
# class B(A):
# def test(self):
# print('from B')
#
#
# class C(A):
# def test(self):
# print('from C')
#
#
# class D(B):
# def test(self):
# print('from D')
#
#
# class E(C):
# def test(self):
# print('from E')
#
#
# class F(D, E):
# # def test(self):
# # print('from F')
# pass
#
#
# f1 = F()
# f1.test()
# # 只有新式纔有這個屬性可以查看線性列表,經典類沒有這個屬性
# print(F.__mro__)
"""
繼承的作用:
# 減少代碼的重用
# 提高代碼可讀性
# 規範編程模式
抽象:抽象即抽取類似或者說比較像的部分。是一個從具題到抽象的過程。
繼承:子類繼承了父類的方法和屬性
派生:子類在父類方法和屬性的基礎上產生了新的方法和屬性
1.多繼承問題
在繼承抽象類的過程中,我們應該儘量避免多繼承;
而在繼承接口的時候,我們反而鼓勵你來多繼承接口
2.方法的實現
在抽象類中,我們可以對一些抽象方法做出基礎實現;
而在接口類中,任何方法都只是一種規範,具體的功能需要子類實現
"""
"""
多態指的是一類事物有多種形態
多態性(多態動態綁定)
多態性是指在不考慮實例類型的情況下使用實例
"""
# # 動物有多種形態:狗,貓,豬
# import abc
#
#
# # 同一類事物:動物
# class Animal(metaclass=abc.ABCMeta):
# @abc.abstractmethod
# def talk(self):
# pass
#
#
# # 動物的形態之一:人
# class Cat(Animal):
# def talk(self):
# print('喵喵')
#
#
# # 動物的形態之二:狗
# class Dog(Animal):
# def talk(self):
# print('汪汪')
#
#
# # 動物的形態之三:豬
# class Pig(Animal):
# def talk(self):
# print('豬昂昂')
#
#
# c1 = Cat()
# d1 = Dog()
# p1 = Pig()
#
# # c1、d1、p1都是動物,只要是動物肯定有talk方法
# # 於是我們可以不用考慮它們三者的具體是什麼類型,而直接使用
# c1.talk()
# d1.talk()
# p1.talk()
#
#
# # 更進一步,我們可以定義一個統一的接口來使用
# def func(obj):
# obj.talk()
#
#
# func(c1)
"""
封裝:隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。
優點:
1. 將變化隔離;
2. 便於使用;
3. 提高複用性;
4. 提高安全性;
封裝的原則:
1. 將不需要對外提供的內容都隱藏起來;
2. 把屬性都隱藏,提供公共方法對其訪問。
私有變量和私有方法:
在python中用雙下劃線開頭的方式將屬性隱藏起來(設置成私有的)
封裝在於明確區分內外,使得類實現者可以修改封裝內的東西而不影響外部調用者的代碼;
"""
# 其實這僅僅這是一種變形操作
# 類中所有雙下劃線開頭的名稱如__x都會自動變形成:_類名__x的形式:
class A:
# 類的數據屬性就應該是共享的,
# 但是語法上是可以把類的數據屬性設置成私有的如__N,會變形爲_A__N
__N = 0
def __init__(self):
# 變形爲self._A__X
self.__X = 10
# 變形爲_A__foo
def __foo(self):
print('from A')
def bar(self):
# 只有在類內部纔可以通過__foo的形式訪問到.
self.__foo()
# A._A__N是可以訪問到的,
# 即這種操作並不是嚴格意義上的限制外部訪問,
# 僅僅只是一種語法意義上的變形
"""
變形的特點:
1.類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。
2.這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。
3.在子類定義的__x不會覆蓋在父類定義的__x,因爲子類中變形成了:
_子類名__x,而父類中變形成了:_父類名__x,
即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。
注意問題:
1.這種機制也並沒有真正意義上限制我們從外部直接訪問屬性,
知道了類名和屬性名就可以拼出名字:_類名__屬性,然後就可以訪問了,如a._A__N
2.變形的過程只在類的內部生效,在定義後的賦值操作,不會變形
3.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義爲私有的
"""
"""
property是一種特殊的屬性,訪問它時會執行一段功能(函數)然後返回值
將一個類的函數定義成property特性以後,使用obj.name的時候,
無法察覺name是執行了一個函數然後計算出來的,這種特性的使用方式遵循了統一訪問的原則
一個靜態屬性property本質就是實現了get,set,delete三種方法
面向對象的封裝有三種方式:
【public】
這種其實就是不封裝,是對外公開的
【protected】
這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,
但我不知道爲什麼大家 不說“女兒”,
就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開
【private】
這種封裝對誰都不公開
"""
# # 計算圓的周長和麪積
# from math import pi
#
#
# class Circle:
# """
# 定義了一個圓形類;
# 提供計算面積(area)和周長(perimeter)的方法
#
# """
# # 圓的半徑
# def __init__(self, radius):
# self.radius = radius
#
# @property
# def area(self):
# return pi * self.radius * self.radius
#
# @property
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# # 實例化一個圓
# c = Circle(10)
# # 計算對象圓的面積和周長並打印
# print(c.area, c.perimeter)
# # 此時的特性area和perimeter不能被賦值
# class Foo:
# def __init__(self, val):
# # 將所有的數據屬性都隱藏起來
# self.__NAME = val
#
# @property
# def name(self):
# # obj.name訪問的是self.__NAME(這也是真實值的存放位置)
# return self.__NAME
#
# @name.setter
# def name(self, value):
# # 在設定值之前進行類型檢查
# if not isinstance(value, str):
# raise TypeError('%s must be str' % value)
# # 通過類型檢查後,將值value存放到真實的位置self.__NAME
# self.__NAME = value
#
# @name.deleter
# def name(self):
# raise TypeError('Can not delete')
#
#
# f = Foo('egon')
# print(f.name)
# # 拋出異常'TypeError: 10 must be str'
# f.name = 10
# # 拋出異常'TypeError: Can not delete'
# del f.name
# # 一個靜態屬性property本質就是實現了get,set,delete三種方法
# class Foo:
#
# @property
# def AAA(self):
# print('get的時候運行我啊')
#
# @AAA.setter
# def AAA(self,value):
# print('set的時候運行我啊')
#
# @AAA.deleter
# def AAA(self):
# print('delete的時候運行我啊')
#
#
# # 只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleter
# f1 = Foo()
# f1.AAA
# f1.AAA = 'aaa'
# del f1.AAA
# class Foo:
# def get_AAA(self):
# print('get的時候運行我啊')
#
# def set_AAA(self,value):
# print('set的時候運行我啊')
#
# def delete_AAA(self):
# print('delete的時候運行我啊')
# # 內置property三個參數與get,set,delete一一對應
# AAA = property(get_AAA, set_AAA, delete_AAA)
#
#
# f1 = Foo()
# f1.AAA
# f1.AAA = 'aaa'
# del f1.AAA
# 使用方式
# class Goods:
#
# def __init__(self):
# # 原價
# self.original_price = 100
# # 折扣
# self.discount = 0.8
#
# @property
# def price(self):
# # 實際價格 = 原價 * 折扣
# new_price = self.original_price * self.discount
# return new_price
#
# @price.setter
# def price(self, value):
# self.original_price = value
#
# @price.deleter
# def price(self):
# del self.original_price
#
#
# obj = Goods()
# # 獲取商品價格
# # obj.price
# # 修改商品原價
# obj.price = 200
# print(obj.price)
# # 刪除商品原價
# del obj.price
# obj.price = 300
# print(obj.price)
"""
封裝器的作用或區別
Classmethod:
Staticmethod
"""
class Classmethod_Demo():
role = 'dog'
@classmethod
def func(cls):
print(cls.role)
Classmethod_Demo.func()
class Staticmethod_Demo():
role = 'dog'
@staticmethod
def func():
print("當普通方法用")
Staticmethod_Demo.func()
class A:
__role = 'CHINA'
@classmethod
def show_role(cls):
print(cls.__role)
@staticmethod
def get_role():
return A.__role
@property
def role(self):
return self.__role
a = A()
print(a.role)
print(a.get_role())
a.show_role()
願有更多的朋友,在網頁筆記結構上分享更邏輯和易讀的形式:
鏈接:暫無
提取碼:暫無