⼀、匿名函數
1. 定義:
顧名思義就是函數沒有名字,使⽤lambda關鍵字定義的函數就是匿名函數,簡化代碼,增加運⾏效率。
普通函數
def func(a,b,c):
return a+b+c
print(func(1,2,3))
匿名函數
result = (lambda a,b,c:a+b+c)(1,2,3)
print(result)
2. 特點:
匿名函數隻適合做一下簡單的操作,返回值不需要加上return,返回值就是該表達式的結果
用匿名函數有個好處,因為函數沒有名字,不必擔心函數名衝突。此外,匿名函數也是一個函數對象,也可以把匿名函數賦值給一個變量,再利用變量來調用該函數
二、面向對象編程
1. 面向對象or面向過程
面向對象編程——Object Oriented Programming,簡稱OOP,是一種程序設計思想。OOP把對象作為程序的基本單 元,一個對象包含了數據和操作數據的函數。
面向過程的程序設計把電腦程式視為一系列的命令集合,即一組函數的順序執行。為了簡化程序設計,面向過程把 函數繼續切分為子函數,即把大塊函數通過切割成小塊函數來降低系統的複雜度。
而面向對象的程序設計把電腦程式視為一組對象的集合,而每個對象都可以接收其他對象發過來的消息,並處理這 些消息,電腦程式的執行就是一系列消息在各個對象之間傳遞。
2. Python面向對象
在Python中,所有數據類型都可以視為對象,當然也可以自定義對象。自定義的對象數據類型就是面向對象中的類 (Class)的概念。
假設我們要處理學生的成績表,為了表示一個學生的成績,面向過程的程序可以用一個dict表示:
std1 = { 'name': 'Curry', 'score': 98 }
std2 = { 'name': 'James', 'score': 81 }
而處理學生成績可以通過函數實現,比如列印學生的成績:
def print_socre(std):
print('%s:%s' % (std['name'],std['score']))
如果採用面向對象的程序設計思想,我們首選思考的不是程序的執行流程,而是Student這種數據類型應該被視為 一個對象,這個對象擁有name和score這兩個屬性(Property)。如果要列印一個學生的成績,首先必須創建出這 個學生對應的對象,然後,給對象發一個print_score消息,讓對象自己把自己的數據列印出來。
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
給對象發消息實際上就是調用對象對應的關聯函數,我們稱之為對象的方法(Method)。面向對象的程序寫出來就 像這樣:
bart = Student('Bart Simpson', 59)
lisa = Student('Lisa Simpson', 87)
bart.print_score()
lisa.print_score()
面向對象的設計思想是從自然界中來的,因為在自然界中,類(Class)和實例(Instance)的概念是很自然的。Class是一種抽象概念,比如我們定義的Class——Student,是指學生這個概念,而實例(Instance)則是一個個具 體的Student,比如,Bart Simpson和Lisa Simpson是兩個具體的Student。
所以,面向對象的設計思想是抽象出Class,根據Class創建Instance。
面向對象的抽象程度又比函數要高,因為一個Class既包含數據,又包含操作數據的方法。
三、類和對象
面向對象編程的2個非常重要的概念:類和對象
對象是面向對象編程的核心,在使用對象的過程中,為了將具有共同特徵和行為的一組對象抽象定義,提出了另外一 個新的概念——類
類就相當於製造飛機時的圖紙,用它來進行創建的飛機就相當於對象。
1. 類
人以類聚物以群分。具有相似內部狀態和運動規律的實體的集合(或統稱為抽象)。具有相同屬性和行為事物的統稱 類是抽象的,在使用的時候通常會找到這個類的一個具體的存在,使用這個具體的存在。一個類可以找到多個對象
2. 對象
某一個具體事物的存在 ,在現實世界中可以是看得見摸得著的。可以是直接使用的
3. 類和對象之間的關係
類就是創建對象的模板
4. 定義類和創建對象
class 類名:
方法列表
經典類(舊式類)定義形式
新式類定義形式
def info(self):
print("hero")
說明:
定義類時有2種形式:新式類和經典類,上面代碼中的Hero為新式類,前兩行注釋部分則為經典類;
object 是Python 裡所有類的最頂級父類;類名 的命名規則按照"大駝峰命名法";
info 是一個實例方法,第一個參數一般是self,表示實例對象本身,當然了可以將self換為其它的名字,其 作用是一個變量 這個變量指向了實例對象.
python中,可以根據已經定義的類去創建出一個或多個對象。
創建對象的格式為:
對象名1 = 類名()
對象名2 = 類名()
對象名3 = 類名()
class Hero(object): Hero這個類 實例化了一個對象
hero = Hero()
. 表示選擇屬性或者方法
hero.info()
print(hero) 實例化了一個英雄對象
hero = Hero()
姓名
hero.hp = 2600 通過.成員選擇運算符,獲取對象的屬性值
print("英雄 %s 的生命值 :%d" % (hero.name, hero.hp))
實例化了一個英雄對象
hero=Hero()
姓名
hero.hp=2600 通過.成員選擇運算符,獲取對象的實例方法
hero.info() Python 的類裡提供的,兩個下劃線開始,兩個下劃線結束的方法,就是魔法方法,__init__()就是一個魔法方法,
通常用來做屬性初始化 或 賦值 操作。
如果為了能夠在完成自己想要的功能,可以自己定義__init__方法,
姓名
self.hp = 2600 實例化了一個英雄對象,並自動調用__init__()方法
hero = Hero()
只需要調用實例方法info(),即可獲取英雄的屬性
hero.move()
總結:
__init__()方法,在創建一個對象時默認被調用,不需要手動調用
__init__(self)中的self參數,不需要開發者傳遞,python解釋器會自動把當前的對象引用傳遞過去。
class Hero(object):
"""定義了一個英雄類,可以移動和攻擊"""
def __init__(self, name, hp):
""" __init__() 方法,用來做變量初始化 或 賦值 操作"""
生命值:
self.hp = hp
def move(self):
"""實例方法"""
print("%s 正在前往事發地點..." % self.name)
def info(self):
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print(gailun)
不同對象的屬性值的單獨保存
print(id(blind.name))
print(id(gailun.name))
父類
class A(object):
def __init__(self):
self.num = 10
def print_num(self):
print(self.num + 10)
定義一個Person類
class Person(object):
def __init__(self):
實例方法
def make_person(self):
print(" <%s> 造了一個人..." % self.name)
子類可以繼承父類所有的屬性和方法,哪怕子類沒有自己的屬性和方法,也可以使用父類的屬性和方法。
pass
panda = Teacher() 子類對象可以直接使用父類的屬性
damao.make_person() 實例變量,屬性
def make_person(self): 多繼承,繼承了多個父類
pass
ls = Person()
print(ls.name)
ls.make_person()
重寫:子類繼承父類,父類的方法滿足不了子類的需要可以對父類的方法進行重寫
調用方法的時候先從本類去找,如果本來沒有再去父類去找,會遵循mro的特點
stu.run()
4. 屬性方法
1. 類屬性和實例屬性
類屬性就是類對象所擁有的屬性,它被所有類對象的實例對象所共有,在內存中只存在一個副本,這個和C++中類的靜態成員變量有點類似。對於公有的類屬性,在類外可以通過類對象和實例對象訪問
class People(object):
name = 'Tom' 私有的類屬性
p = People()
print(p.name) 正確
print(p.__age) 錯誤,不能在類外通過類對象訪問私有的類屬性
實例屬性(對象屬性)
class People(object):
address = '山東' 實例屬性
self.age = 20 實例屬性
print(p.address) 正確
print(p.age) 正確
print(People.name) 錯誤
類屬性
print(People.country) p = People()
print(p.country) p.country = 'japan'
print(p.country) 刪除實例屬性
print(p.country)
總結
如果需要在類外修改類屬性,必須通過類對象去引用然後進行修改。如果通過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性,並且之後如果通過實例對象去引用該名稱的屬性,實例屬性會強制屏蔽掉類屬性,即引用的是實例屬性,除非刪除了該實例屬性。
2.靜態方法和類方法
(1)類方法
是類對象所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個參數必須是類對象,一般以cls作為第一個參數(當然可以用其他名稱的變量作為其第一個參數,但是大部分人都習慣以'cls'作為第一個參數的名字,就最好用'cls'了),能夠通過實例對象和類對象去訪問。
class People(object):
country = 'china'
可以用過實例對象引用
print(People.get_country()) 類方法,用classmethod來進行修飾
@classmethod
def get_country(cls):
return cls.country
@classmethod
def set_country(cls,country):
cls.country = country
p = People()
print(p.get_country()) 可以通過類訪問
p.set_country('japan')
print(p.get_country())
print(People.get_country())
靜態方法
def get_country():
return People.country
p = People()
通過類訪問靜態方法
print(People.get_country())
總結
從類方法和實例方法以及靜態方法的定義形式就可以看出來,類方法的第一個參數是類對象cls,那麼通過cls引用的必定是類對象的屬性和方法;實例方法的第一個參數是實例對象self,那麼通過self引用的可能是類屬性、也有可能是實例屬性(這個需要具體分析),不過在存在相同名稱的類屬性和實例屬性的情況下,實例屬性優先級更高。靜態方法中不需要額外定義參數,因此在靜態方法中引用類屬性的話,必須通過類實例對象來引用
六、多態
'''
多態, 不同的 子類對象調用 相同的 父類方法,產生 不同的 執行結果,可以增加代碼的外部 調用靈活度
多態以 繼承 和 重寫 父類方法 為前提
多態是調用方法的技巧,不會影響到類的內部設計
'''
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(object):
def run(self):
print('Dog is running...')
class Cat(object):
def run(self):
print('Cat is running...')
# 定義一個方法
def run_twice(animal):
animal.run()
animal.run()
dog = Dog()
cat = Cat()
run_twice(dog)
run_twice(cat)