python_面向對象編程

1、面向對象編程python

# 1.什麼是面向對象
    面向過程與面向對象
        面向過程編程:解決問題從過程出發,解決問題步驟化

        面向對象編程:解決問題從對象出發,解決問題找對象

    對象與類
        類:對象的類型 => 數字
            具備相同特徵與行爲集合的抽象

        對象:類的具體表現 => 數字10
            類的實例化,就是具備特徵與行爲實際存在的個體(每個對象都是惟一的)

# 2.爲何要面向對象編程
        面向過程:開發成本高,解決問題侷限性小
        面向對象:開發成本低,解決問題侷限於對象

        問題:'abc' => {'a', 'b', 'c'}
            面向過程: 本身寫
            面向對象:str => list => set  #(引用模塊)

        開發:優選面向對象(找解決問題的對象),
        再考慮找多個對象(面向對象與面向過程的結合),
        最後本身去封裝一個能夠解決問題的對象(對外是面向對象的體現,內部解決問題的核心是面向過程)

# 例如:
s = 'abc'  # => ['a', 'b', 'c']
# 解決方案
# re.findall()  list初始化方法
# for循環append

# 面向過程:解決問題步驟化
res = []
for c in s:
    res.append(c)
print(res)

# 面向對象:解決問題找對象
#       -- 對象如何解決問題:對象.解決問題的方法()

# 找re對象
import re
res = re.findall(r'[a-z]', s)
print(res)

# 找list對象
res = list(s)
print(res)

# 模塊 md.py
def print_num(a):
    print(a)

from md import print_num as pn
pn(100)
pn(200)

2、類的聲明語法linux

class 類名:
    # 在該縮進下(在類下)定義多個函數,類名就能夠總體管理全部的函數,經過點語法來調用具體的函數
    def fn1():
        print('fn1 run')
    def fn2():
        print('fn2 run')
    def fn3():
        print('fn3 run')
        
# 類名的命名規範:採用大駝峯

3、點語法與名稱空間算法

def fn():
    pass

class Fn():
    def a_fn():
        pass
    pass

import md

print(fn, fn.__dict__)
# <function fn at 0x0000000001CF2EA0> {}

print(Fn, Fn.__dict__)
# <class '__main__.Fn'> {'__module__': '__main__', 'a_fn': <function Fn.a_fn at 0x0000000002947048>, '__dict__': <attribute '__dict__' of 'Fn' objects>, '__weakref__': <attribute '__weakref__' of 'Fn' objects>, '__doc__': None}

print(md, md.__dict__)
#<module 'md' from 'F:\\安裝包\\JetBrains\\JetBrains\\Projects\\09\\代碼\\part2\\md.py'> {'__name__': 'md', '__doc__': None, '__package__': '', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000001EA6E10>, '__spec__': ModuleSpec(name='md', loader=<_frozen_importlib_external.SourceFileLoader object at 0x0000000001EA6E10>, origin='F:\\安裝包\\JetBrains\\JetBrains\\Projects\\09\\代碼\\part2\\md.py'), '__file__': 'F:\\安裝包\\JetBrains\\JetBrains\\Projects\\09\\代碼\\part2\\md.py', '__cached__': 'F:\\安裝包\\JetBrains\\JetBrains\\Projects\\09\\代碼\\part2\\__pycache__\\md.cpython-36.pyc', '__builtins__': {'__name__': 'builtins', '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", '__package__': '', '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>), '__build_class__': <built-in function __build_class__>, '__import__': <built-in function __import__>, 'abs': <built-in function abs>, 'all': <built-in function all>, 'any': <built-in function any>, 'ascii': <built-in function ascii>, 'bin': <built-in function bin>, 'callable': <built-in function callable>, 'chr': <built-in function chr>, 'compile': <built-in function compile>, 'delattr': <built-in function delattr>, 'dir': <built-in function dir>, 'divmod': <built-in function divmod>, 'eval': <built-in function eval>, 'exec': <built-in function exec>, 'format': <built-in function format>, 'getattr': <built-in function getattr>, 'globals': <built-in function globals>, 'hasattr': <built-in function hasattr>, 'hash': <built-in function hash>, 'hex': <built-in function hex>, 'id': <built-in function id>, 'input': <built-in function input>, 'isinstance': <built-in function isinstance>, 'issubclass': <built-in function issubclass>, 'iter': <built-in function iter>, 'len': <built-in function len>, 'locals': <built-in function locals>, 'max': <built-in function max>, 'min': <built-in function min>, 'next': <built-in function next>, 'oct': <built-in function oct>, 'ord': <built-in function ord>, 'pow': <built-in function pow>, 'print': <built-in function print>, 'repr': <built-in function repr>, 'round': <built-in function round>, 'setattr': <built-in function setattr>, 'sorted': <built-in function sorted>, 'sum': <built-in function sum>, 'vars': <built-in function vars>, 'None': None, 'Ellipsis': Ellipsis, 'NotImplemented': NotImplemented, 'False': False, 'True': True, 'bool': <class 'bool'>, 'memoryview': <class 'memoryview'>, 'bytearray': <class 'bytearray'>, 'bytes': <class 'bytes'>, 'classmethod': <class 'classmethod'>, 'complex': <class 'complex'>, 'dict': <class 'dict'>, 'enumerate': <class 'enumerate'>, 'filter': <class 'filter'>, 'float': <class 'float'>, 'frozenset': <class 'frozenset'>, 'property': <class 'property'>, 'int': <class 'int'>, 'list': <class 'list'>, 'map': <class 'map'>, 'object': <class 'object'>, 'range': <class 'range'>, 'reversed': <class 'reversed'>, 'set': <class 'set'>, 'slice': <class 'slice'>, 'staticmethod': <class 'staticmethod'>, 'str': <class 'str'>, 'super': <class 'super'>, 'tuple': <class 'tuple'>, 'type': <class 'type'>, 'zip': <class 'zip'>, '__debug__': True, 'BaseException': <class 'BaseException'>, 'Exception': <class 'Exception'>, 'TypeError': <class 'TypeError'>, 'StopAsyncIteration': <class 'StopAsyncIteration'>, 'StopIteration': <class 'StopIteration'>, 'GeneratorExit': <class 'GeneratorExit'>, 'SystemExit': <class 'SystemExit'>, 'KeyboardInterrupt': <class 'KeyboardInterrupt'>, 'ImportError': <class 'ImportError'>, 'ModuleNotFoundError': <class 'ModuleNotFoundError'>, 'OSError': <class 'OSError'>, 'EnvironmentError': <class 'OSError'>, 'IOError': <class 'OSError'>, 'WindowsError': <class 'OSError'>, 'EOFError': <class 'EOFError'>, 'RuntimeError': <class 'RuntimeError'>, 'RecursionError': <class 'RecursionError'>, 'NotImplementedError': <class 'NotImplementedError'>, 'NameError': <class 'NameError'>, 'UnboundLocalError': <class 'UnboundLocalError'>, 'AttributeError': <class 'AttributeError'>, 'SyntaxError': <class 'SyntaxError'>, 'IndentationError': <class 'IndentationError'>, 'TabError': <class 'TabError'>, 'LookupError': <class 'LookupError'>, 'IndexError': <class 'IndexError'>, 'KeyError': <class 'KeyError'>, 'ValueError': <class 'ValueError'>, 'UnicodeError': <class 'UnicodeError'>, 'UnicodeEncodeError': <class 'UnicodeEncodeError'>, 'UnicodeDecodeError': <class 'UnicodeDecodeError'>, 'UnicodeTranslateError': <class 'UnicodeTranslateError'>, 'AssertionError': <class 'AssertionError'>, 'ArithmeticError': <class 'ArithmeticError'>, 'FloatingPointError': <class 'FloatingPointError'>, 'OverflowError': <class 'OverflowError'>, 'ZeroDivisionError': <class 'ZeroDivisionError'>, 'SystemError': <class 'SystemError'>, 'ReferenceError': <class 'ReferenceError'>, 'BufferError': <class 'BufferError'>, 'MemoryError': <class 'MemoryError'>, 'Warning': <class 'Warning'>, 'UserWarning': <class 'UserWarning'>, 'DeprecationWarning': <class 'DeprecationWarning'>, 'PendingDeprecationWarning': <class 'PendingDeprecationWarning'>, 'SyntaxWarning': <class 'SyntaxWarning'>, 'RuntimeWarning': <class 'RuntimeWarning'>, 'FutureWarning': <class 'FutureWarning'>, 'ImportWarning': <class 'ImportWarning'>, 'UnicodeWarning': <class 'UnicodeWarning'>, 'BytesWarning': <class 'BytesWarning'>, 'ResourceWarning': <class 'ResourceWarning'>, 'ConnectionError': <class 'ConnectionError'>, 'BlockingIOError': <class 'BlockingIOError'>, 'BrokenPipeError': <class 'BrokenPipeError'>, 'ChildProcessError': <class 'ChildProcessError'>, 'ConnectionAbortedError': <class 'ConnectionAbortedError'>, 'ConnectionRefusedError': <class 'ConnectionRefusedError'>, 'ConnectionResetError': <class 'ConnectionResetError'>, 'FileExistsError': <class 'FileExistsError'>, 'FileNotFoundError': <class 'FileNotFoundError'>, 'IsADirectoryError': <class 'IsADirectoryError'>, 'NotADirectoryError': <class 'NotADirectoryError'>, 'InterruptedError': <class 'InterruptedError'>, 'PermissionError': <class 'PermissionError'>, 'ProcessLookupError': <class 'ProcessLookupError'>, 'TimeoutError': <class 'TimeoutError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-Z plus Return to exit, 'exit': Use exit() or Ctrl-Z plus Return to exit, 'copyright': Copyright (c) 2001-2017 Python Software Foundation.
# All Rights Reserved. ...

# 訪問名字的底層
print(Fn.__dict__['__module__'])  # __main__
# 訪問名字的語法優化
print(Fn.__module__)  # __main__
# 總結:對象.名字 本質 對象.__dict__['名字']


# 賦值
fn.name = '我寫的函數'
print(fn.__dict__)  # {'name': '我寫的函數'}
print(fn.__dict__['name']) # 我寫的函數
print(fn.name) # 我寫的函數

# 瞭解:對象的名稱空間,與對象內部的名稱空間不是同一個
print('========================================')
def func():
    a = 10
    b = 20
    print(locals()) # {'b': 20, 'a': 10}
func()
print(func.__dict__)  # {}

# 記住:
# 對象.名字 = 值 是爲該對象添加一個名稱空間的名字,
# 也只能經過 對象.名字 來使用
func.name = 'func function'
print(func.name) # func function
View Code
# 能夠產生名稱空間的語法

def fn():  # 具備名稱空間:fn.__dict__
    pass

class Fn():  # 具備名稱空間:Fn.__dict__
    pass

import md  # 具備名稱空間:md.__dict__


# 名稱空間如何爲一個名字設置值,或訪問一個名字對應的值
fn.__dict__[名字] = 值  # 設置值
print(fn.__dict__[名字])  # 取值


# 重點:名稱空間取值賦值的語法優化:點語法
fn.名字 = 值  # 設置值
print(fn.名字)  # 取值

4、類與對象的聲明編程

class People:
    name = ''
    
p1 = People()
p2 = People()

# 結論1:類與每個對象的名稱空間都是獨立的
print(p1.__dict__)  # {}
print(p2.__dict__)  # {}
print(People.__dict__)  # {'name': '人', ...系統的}

# 結論2:類與每個對象均可以使用類中的名字
print(People.name)  #
print(p1.name)  #
print(p2.name)  #

# 結論3:對象訪問名字,優先訪問本身的,本身沒有再訪問類的
p1.name = '張三'
p2.user = '李四'
print(People.name)  #
print(p1.name)  # 張三
print(p2.user)  # 李四
print(p2.name)  #

# 重點:
# 對象操做名字,操做的是對象的,類操做名字操做的是類的,之間相互不干預
# 類只能訪問類的名字
# 對象訪問名字,優先訪問自身的,自身沒有再訪問類的

5、類的初始化方法安全

# 能夠快速爲類實例化出的每個對象,產生對象名稱空間中的多個名字

class NewTeacher:
    def __init__(self, name, sex, age):
        # print(id(self))  # self就是實例化產生的對象(nt1)
        # print('init 被調用了')
        self.name = name
        self.sex = sex
        self.age = age
    pass

# 類()就是在調用類的__init__方法
nt1 = NewTeacher('王大錘', '', 58)
# print(id(nt1))
print(nt1.name, nt1.sex, nt1.age)


nt2 = NewTeacher('王小錘', '', 48)
print(nt2.name, nt2.sex, nt2.age)

演化:app

class Teacher:
    name = '教授'

def set_obj(obj, name, sex, age):
    obj.name = name
    obj.sex = sex
    obj.age = age

t1 = Teacher()
# t1.name = 'C老師'
# t1.sex = "女"
# t1.age = 36
set_obj(t1, 'C老師', "", 36)
print(t1.name, t1.sex, t1.age)

t2 = Teacher()  # 類()應該就是函數的調用,函數調用能夠傳參,能優化屬性的賦值
# t2.name = 'W老師'
# t2.sex = "女"
# t2.age = 28
set_obj(t2, 'W老師', "", 28)
print(t2.name, t2.sex, t2.age)

# t3 = Teacher()
# set_obj(t3, '王大錘', '男', 58)

# 能不能再優化 => t3 = Teacher('王大錘', '男', 58)
# print(t3.name, t3.sex, t3.age)
例子

6、類的方法分類ide

# 對象方法:直接定義的方法,建議由對象調用,類中內部須要使用對象的數據時的方法要定義爲對象方法
# 1.對象方法對象調用,默認傳入對象給第一個形參 
class 類名:
    def fn(self, *args, **kwargs): pass

# 類方法:被classmethod修飾的方法,建議由類調用,類中內部須要使用類的數據時的方法要定義爲類方法
# 2.類方法由類調用,默認傳入類給第一個形參
class 類名:
    @classmethod
    def fn(cls, *args, **kwargs): pass

# 靜態方法:被staticmethod修飾的方法,建議由類調用,類中內部不須要類相關數據時的方法要定義爲靜態方法
# 3.靜態方法建議由類調用,默認不傳入調用者
    @staticmethod
    def fn(*args, **kwargs): pass

案例1:函數

class Student:
    name = '學生'
    def __init__(self, name, id_num):
        self.name = name
        self.id_num = id_num

    # 對象(成員)方法
    def study(self):  # 在類中產生的全部方法,都是屬於類的,可是對象能夠調用
        # print('self>>', id(self))
        print("%s在學習" % self.name)

    # 類方法: 第一個參數就是用來接收調用者,類方法的調用者必定是類,因此第一個參數命名約定爲cls
    @classmethod
    def fn(cls):
        print(id(cls))


    # 靜態方法
    @staticmethod
    def func():
        print('func run')

stu1 = Student('Bob', 1)
print(stu1.__dict__)  # {'name': 'Bob', 'id_num': 1}
print(stu1.name) # Bob
# stu1.__dict__.clear()  # 清空stu1
# print(stu1.__dict__)  # {}
# print(stu1.name) # 學生

print("====================")
stu2 = Student('Tom', 2)
stu1.study() # Bob在學習
print(id(stu1)) # 32140984
stu2.study() # Tom在學習
print(id(stu2)) #
print("====================")
# 結論1:對象調用類中的方法,默認隱式將對象自身傳入,在方法中,第一個參數用self來接受傳入的對象
# Student.fn(Student) => Student.fn()
# print(id(Student))

Student.fn() # 41758904
print(id(Student)) # 41758904

# 結論2:類中用@classmethod裝飾的方法,是類方法,用類來調用,默認會將類傳入給方法的第一個參數

print("====================")
Student.func() # func run
stu1.func() # func run
# 結論3:類中用@staticmethod裝飾的方法,是靜態方法,能夠被類和對象調用,默認不會將類或對象傳入
View Code

案例二:類的不一樣方法應用工具

# 案例
class Book:
    name = ''
    def __init__(self, name, price):
        self.name = name
        self.price = price

    # 書的詳情信息 => 必定須要知道哪本書
    # @classmethod  # 類調用cls就是類,對象調用處理成 對象.__class__

    def detail(self):
        # print(cls.name)
        print("%s的價格爲:%s元" % (self.name, self.price))

book1 = Book('西遊記', 38.8)
book2 = Book('三國', 88.8)
book1.detail()
book2.detail()
# print(book1.__class__)


# 靜態方法:方法的內部不須要對象及類的參與,因此定義爲靜態方法,可是方法必須由調用者,建議用類就能夠了
class NumTool:  # 工具類 => 模塊
    def max_two(self, n1, n2):
        max_num = n1 if n1 > n2 else n2
        print('大數是%s' % max_num)

    @staticmethod
    def new_max_two(n1, n2):
        max_num = n1 if n1 > n2 else n2
        print('大數是%s' % max_num)

n1 = NumTool()
n2 = NumTool()
n1.max_two(10, 20)
n2.max_two(10, 20)

NumTool.new_max_two(10, 20)
n1.new_max_two(10, 20)


# 類方法:方法的內部須要類的參與,因此定義爲類方法,第一個參數默認傳類
class NewNumTool:
    PI = 3.14

    @classmethod
    def new_max_two(cls, n1, n2):
        max_num = n1 if n1 > n2 else n2
        return max_num

    @classmethod
    def new_max_three(cls, n1, n2, n3):
        # max_num = "想去複用new_max_two"
        max_num = cls.new_max_two(n1, n2)
        max_num = cls.new_max_two(max_num, n3)
        return max_num

    @classmethod
    def is_PI(cls, num):
        if num == cls.PI:
            return True
        return False


res = NewNumTool.new_max_three(1, 5, 3)
print('大數是%s' % res)

print(NewNumTool.is_PI(3.149))
View Code

 7、封裝學習

# 什麼是封裝:將類的一下屬性和方法對外隱藏,對內可見
# 爲何要封裝:爲屬性和方法的操做添加權限,具體權限都是經過自定義邏輯來處理

# 封裝的手段:在類屬性方法,對象屬性方法,靜態方法名字前添加 __
# 只要是經過 __名字 這種命名規範,就是對外隱藏
    # 本質:__名字 封裝隱藏變量的本質是 將名字修飾成 _類名__名字

# 對外解決封裝的方式
# 1.若是真的不想讓外界訪問,就不對外提供訪問數據的方法
# 2.若是想讓外界訪問,能夠對外提供訪問數據的方法,方法具備邏輯,使用能夠添加操做權限
class Test:
    def __init__(self, name):
        # __name只是對外隱藏,對內可見
        self.__name = name

    def get_name(self):
        return self.__name

    def set_name(self, name):
        if 'sb' not in name:  # 對數據的修改可能會產生數據的安全性問題,能夠添加限制條件
            self.__name = name
# 重點:封裝的對外訪問語法的優化
class User:
    def __init__(self, name):
        self.__name = name

    @property  # 將方法假裝成屬性
    def name(self):
        return self.__name

    @name.setter  # 能爲有假裝get方法的(方法)屬性,再假裝set方法
    def name(self, value):
        self.__name = value

    @name.deleter
    def name(self):
        del self.__name
        
    # 總結:
    # 1.對象沒了,對象的屬性也就沒了,因此不須要屬性 @名字.deleter
    # 2.對外提供get方法是基礎,@property,若是沒有,外界不可讀不可寫
    # 3.若是有@property,則能夠 @名字.setter,有set,爲可讀可寫,無set爲只讀

    @property  # 假裝的屬性方法,不須要必定有 __開頭 的名字與之對應
    def pwd(self):
        return '123456'

u1 = User('Owen')
print(u1.name)  # 若是一個方法假裝成屬性,對象.方法名 就會自動調用該方法

u1.name = 'Zero'
print(u1.name)

# del u1.name
# print(u1.name)

print(u1.pwd)

#@property 將方法假裝成屬性,從而能夠像__init__裏的屬性同樣調用u1.name

 8、類的繼承

什麼是繼承
    繼承是一種新建類的方式,繼承的類稱之爲子類或派生類
    被繼承的類稱之爲父類或基類或超類
    子類繼承父類,也就意味着子類繼承了父類全部的屬性和方法
    能夠直接調用
爲何要有繼承
    減小代碼冗餘
如何使用
class Parent1:
    pass
class Parent2:
    pass
class Son1(Parent1):
    pass
# python中支持多繼承
class Son2(Parent1,Parent2):
    pass
# 如何查看類的父類
print(Son1.__bases__) # (<class '__main__.Parent1'>,)
print(Son2.__bases__) # (<class '__main__.Parent1'>, <class '__main__.Parent2'>)
# 自定義的沒有顯示繼承任何類的父類到底有沒有偷偷繼承某個類呢?
print(Parent1.__bases__) # (<class 'object'>,)
print(Parent2.__bases__) # (<class 'object'>,)
# python2:類若是沒有顯示繼承任何類的狀況下,不繼承任何類
# python3:類若是沒有顯示繼承任何類的狀況下,默認都繼承object類
 經典類與新式類
   經典類:
        不繼承object或者其子類的類  叫經典類  
   新式類: 
        繼承object或者其子類的類    叫新式類
# ps:經典類與新式類只在python2有區分
#python3中只有新式類

派生:

# 派生:在繼承了父類的屬性和方法的基礎之上 本身定義了其餘的屬性和方法
# 若是派生出的方法與父類的同名了 那麼至關於覆蓋了父類的方法

# 類:一系列對象類似的特徵與技能的結合體
# 類與類之間類似的特徵與技能的結合體  >>> 父類
# 類:一系列對象類似的特徵與技能的結合體
# 類與類之間類似的特徵與技能的結合體  >>> 父類
import pickle
class OldboyPeople:
    school = 'oldboy'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def save(self):
        with open(self.name,'wb') as f:
            pickle.dump(self,f)

class OldboyStudent(OldboyPeople):
    def choose_course(self):
        print('%s is choosing course'%self.name)


class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,gender,level):
        OldboyPeople.__init__(self,name,age,gender)
        self.level = level

    def score(self):
        print('%s is score'%self.name)

stu = OldboyStudent('simon',18,'male')
print(stu.name) # simon
stu.save() # 建立文件存數據

tea = OldboyTeacher('xc',18,'male',10)
print(tea.name) # simon
tea.save()

子類方法中調用父類的方法:

 # 方法一:指名道姓
# OldboyPeople.__init__(self,name,age,gender)   跟繼承一點關係都沒有

# 方法二:和繼承有關係
# 單繼承狀況下的屬性查找
class B:
    def f1(self):
        print('from B f1')

    def f2(self):
        print('from B f2')
        self.f1()
class A(B):
    def f1(self):
        print('from A f1')
obj = A()
obj.f2()
"""
from B f2
from A f1
"""
# 上面的例子能夠看出:類是查找順序是先查找本身,再查找父類

# 多繼承
# 不管是python2仍是python3繼承都遵循深度優先(菱型繼承除外)
# 深度優先:依次先從左邊分支查找完後向右查找
# # 多繼承
class D:
    # def test(self):
    #     print('D')
    pass
class E:
    def test(self):
        print('E')
class F:
    def test(self):
        print('F')
class A(D):
    # def test(self):
    #     print('A')
    pass
class B(E):
    # def test(self):
    #     print('B')
    pass
class C(F):
    def test(self):
        print('C')
class G(A,B,C):
    # def test(self):
    #     print('G')
    pass

obj = G()
obj.test() # E
View Code
# 調用方式
import pickle
class OldboyPeople:
    school = 'oldboy'
    def __init__(self,name,age,gender):
        self.name = name
        self.age = age
        self.gender = gender
    def save(self):
        with open(self.name,'wb') as f:
            pickle.dump(self,f)


class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,gender,level):
        # OldboyPeople.__init__(self,name,age,gender)
        # super(OldboyTeacher,self).__init__(name,age,gender)
        super().__init__(name,age,gender) # 調用
        self.level = level
tea = OldboyTeacher('ymc',18,'male',10)
print(tea.name) # ymc
tea.save()

MRO列表,C3算法

# mro列表   C3算法
class D:
    pass
class E:
    pass
class F:
    pass
class A(D):
    pass
class B(E):
    pass
class C(F):
    pass
class G(A,B,C):
    pass

print(G.mro()) """ G A D B E C F [<class '__main__.G'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.F'>, <class 'object'>] """
# super是嚴格按照mro列表的順序調用父類的方法的!!!
class A:
    def f1(self):
        print('from a f1')
    def f2(self):
        print('from a f2')
        super().f1()
class B:
    def f1(self):
        print('from b f1')
    def f2(self):
        print('from b f2')
class C(A,B):
    def f1(self):
        print('from c f1')
print(C.mro())
# [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
obj = C()
obj.f2()
"""
from a f2
from b f1
"""

9、多態與多態性

# 什麼是多態
    一種事物的不一樣形態(動物:人,狗,貓),代碼層面上來講其實就是繼承      
# 爲何要有多態
    多態僅僅是一個概念
# 多態性:在不須要考慮對象具體類型的狀況下 調用對象的方法    
# 如何使用
class Animal:
    def talk(self):
        pass
class People(Animal):
    def talk(self):
        print('hello')
class Dog(Animal):
    def talk(self):
        print('wangwang')
class Cat(Animal):
    def talk(self):
        print('miaomiao')
people = People()
dog = Dog()
cat = Cat()

people.talk()
dog.talk()
cat.talk()

# 例如:len獲取長度

10、反射

# 經過字符串來操做對象的屬性或方法
# 經過字符串來操做對象的屬性或方法
class User:
    school = 'oldgirl'
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print('func')

# hasattr判斷對象是否有某個屬性或方法
print(User.school) # oldgirl
print('school' in User.__dict__) # True
print('xxx' in User.__dict__) # False
print(hasattr(User,'school')) # True
print(hasattr(User,'xxx')) # False
print(hasattr(User,'func')) # True
print('func' in User.__dict__) # True
d = {'name':"jason"}
print(d.get('password','hahahahahaha'))  # hahahahahaha

# getattr 取類中的屬性或方法
print(getattr(User,'school')) # oldgirl
print(getattr(User,'func')) # <function User.func at 0x00000000021F7048>
print(User.__dict__['school']) # oldgirl
print(User.__dict__['func']) # <function User.func at 0x00000000027D7048>
# print(getattr(User,'xxx')) # 獲取沒有的報錯
if hasattr(User,'xxx'):
    getattr(User,'xxx')

# setattr
obj = User('simon',18)
setattr(obj,'gender','male')  # obj.gender = 'male'
print(obj.__dict__)

# delattr
delattr(User,'school')
print(User.__dict__)

11、內置方法

 

class User:
    def __init__(self,name,password):
        self.name = name
        self.password = password

    def __str__(self):
        # return '%s:%s'%(self.name,self.password)
        return '我被打印了,自動觸發'

    def __getattr__(self, item):
        print(item)

    def __setattr__(self, key, value):
        print(key,value)

# __str__對象被執行了打印操做  自動觸發
obj = User('simon',123)
print(User)
print(obj)
"""
name simon
password 123
<class '__main__.User'>
我被打印了,自動觸發
"""

# __getattr__ 當對象獲取一個不存在的屬性時候纔會觸發
obj = User('simon',18)
print(obj.name)
"""
name simon
password 18
name
None
"""

# __setattr__: obj.name = 'xxx'  固定句式
obj = User('simon',18)
obj.sex = 'sexy'
"""
name simon
password 18
sex sexy
"""

class Demo(dict):
    def __getattr__(self, item):
        return self.get(item)
d = Demo(name='simon',password=123)
print(d.name) # simon
print(d.password) # 123

做業一:

1.自定義一個 Fruit 類:該類有一個 類屬性: identify:值爲"水果",有兩個對象屬性: name,price:值由實例化對象時賦值,
一個類方法: get_identify:打印類屬性identify的值,
一個對象方法:get_total_price(num):打印『%s個%s值%s錢』,
一個靜態方法:packing(*fruits) 靜態方法(裝箱)的思路分析 red_apple = Fruit("紅蘋果", 10) green_apple = Fruit("青蘋果", 10) yellow_banana = Fruit("黃香蕉", 8) 調用:Frulit.packing(red_apple, green_apple, yellow_banana) 打印:一箱裝了2個蘋果1個香蕉 2.自定義一個 Person 類,該類具備 name、weight、height、sex 四個對象屬性, -- 對name屬性進行封裝,可是外界任然能夠訪問name以及設置name -- 有一個方法屬性bmi(標準體重),能夠獲取一我的的bmi,bmi只讀不可寫,bmi計算規則 -- 男:(身高cm-80)× 70﹪ | 女:(身高cm-70)× 60﹪ 提示:類屬性就是直接寫在類中的變量,對象屬性就是寫在__init__方法中的用self.屬性 = 值 賦值的屬性,方法屬性就是用 @property 修飾的方法假裝成的屬性 4.用面向對象實現 植物大戰殭屍遊戲 1).定義一個殭屍Zombie類,該類能夠實例化出多種殭屍對象,殭屍對象產生默認都有 名字name、血量HP、防具armor -- 名字:普通殭屍 | 路障殭屍 | 鐵桶殭屍 -- 血量:默認就是100,不須要外界提供 -- 防具:不須要外界提供,從名字中分析肯定,防具的值是一個列表,從名字分析獲得 -- ['', 0] | ['路障', 5] | ['鐵桶', 15] => [防具名, 防具的防護值] -- 經過@property的getter、setter方式,對外提供防具的兩個訪問接口armor_name與armor_count -- armor_name能夠取值、賦值、刪除值:經過一個 -- eg: 普通殭屍對象.armor_name = '鐵桶',不只改變了防具名 -- 普通殭屍對象的名字name也會變成 鐵桶殭屍 -- armor_count只能夠取值 2).定義一個角色User類,該類有名字name屬性、以及打殭屍的beat方法 -- 名字:隨意自定義 -- beat:該方法須要傳入一個殭屍對象 -- 在方法內部能夠實現:某某用戶攻擊了某某個殭屍,殭屍損失多少血,還剩多少血 -- 每一次攻擊,都固定扣除25滴血,可是不一樣的殭屍會被防具相應抵消掉必定的傷害值 -- 循環攻擊殭屍,3s攻擊一次,殭屍被擊殺後,打印 某某用戶擊殺了某某個殭屍 並結束方法 3).定義一個Game類,該類有一個name屬性,屬性值爲 "植物大戰殭屍" ,該類中有一個start方法,經過Game.start()來啓動遊戲 -- 遊戲一開始先顯示遊戲的名字 植物大戰殭屍遊戲 -- 會隨機產生三種殭屍,總共產生三個做爲要被擊殺的對象 -- 生成一個有角色名的角色,依次去擊殺隨機產生的每一隻殭屍 -- 開始擊殺第一隻殭屍 => 某某用戶攻擊了某某個殭屍,殭屍損失多少血,還剩多少血 => 某某用戶擊殺了某某個殭屍 => 第一隻殭屍已被擊殺完畢 => 開始擊殺第二隻殭屍 ... => 第三隻殭屍已被擊殺完畢

做業二:

角色:學校、學員、課程、講師要求:1. 建立北京、上海 2 所學校---學校2. 建立linux , python , go 3個課程 , linux\py 在北京開, go 在上海開  ----課程、地點3. 課程包含,週期,價格,經過學校建立課程-----時間、價格、4. 經過學校建立班級, 班級關聯課程、講師---班級、課程、講師5. 建立學員時,選擇學校,關聯班級  ---學員、學校、班級5. 建立講師角色時要關聯學校,---講師、學校6. 提供兩個角色接口6.1 學員視圖, 能夠註冊, 交學費, 選擇班級,---》註冊、學費、班級6.2 講師視圖, 講師可管理本身的班級, 上課時選擇班級, 查看班級學員列表 , 修改所管理的學員的成績6.3 管理視圖,建立講師, 建立班級,建立課程7. 上面的操做產生的數據都經過pickle序列化保存到文件裏
相關文章
相關標籤/搜索