1. 程式人生 > >1.面向過程程式設計 2.面向物件程式設計 3.類和物件 4.python 建立類和物件 如何使用物件 5.屬性的查詢順序 6.初始化函式 7.繫結方法 與非繫結方法

1.面向過程程式設計 2.面向物件程式設計 3.類和物件 4.python 建立類和物件 如何使用物件 5.屬性的查詢順序 6.初始化函式 7.繫結方法 與非繫結方法

1.面向過程程式設計

面向過程:一種程式設計思想
在編寫程式碼時 要時刻想著過程這個兩個字
過程指的是什麼? 解決問題的步驟 流程,即第一步幹什麼 第二步幹什麼,
其目的是將一個複雜的問題,拆分為若干的小的問題,按照步驟一一解決,
也可以說 將一個複雜的問題,流程化(為其制定一個固定的實現流程),從而變得簡單化
例如:要將大象裝進冰箱
  開啟冰箱
  裝進大象
  關閉冰箱門
以上實現方式 是面向過程的實現方式

面向過程程式設計優缺點:
  優點:複雜的問題,簡單化,
  缺點:由於其實現流程是固定的,一旦中間某一個步驟發生了修改,將導致整體都需要修改
    牽一髮動全身.解釋:本來有一個實現某個功能的固定的流程,後來需要在原來的基礎上增加新的功能,這時候得全部重新設計一遍
    擴充套件性差,維護性差
例如工廠裡流水線,一旦中間某個崗位出來問題,整體就無法正常執行,第一個沒做完,第二個做不了

使用場景:對擴充套件性要求較低的軟體,比如系統核心,指令碼程式(運維工程師寫的程式,其目的就是安裝一堆軟體),Apache HTTP伺服器

 

2.面向物件程式設計

面向物件:一種程式設計思想,即編寫程式碼的方式方法
OOP,是Object oriented Programming的簡稱
將程式看做是一堆物件的集合,實現功能的方式就是物件之間互動來實現

例如:要開一家公司
  1.僱個財務
  2.僱個人事主管
  3.僱幾個夥計
  4.僱個祕書
  5.給他們下達命令
以上方式不是面向過程,為什麼?因為其不關係 財務如何算賬,也不關心人事如何招人,只關心給他們下達命令
而是面向物件是: 財務,人事主管,幾個夥計,祕書

面向物件的優缺點:
優點:
1.不用考慮繁瑣的實現步驟,從一個操作工,變成了老闆
2.擴充套件性高了,當需要一個新功能時,搞一個具備新功能的物件,命令它去完成任務
3.各個物件之間的耦合度低,當一個一個物件出現了問題,不會對其他物件產生影響
4.可維護性高
缺點:

1.面向物件的複雜度比面向過程高
2.無法預知執行結果,就像lol的遊戲過程,一定不能把過程寫死,每個英雄的行為是不固定的
使用場景:需要較高的擴充套件性時,(直接與使用者發生互動的程式例如,qq微信),對於不需要擴充套件的程式而言,使用面向物件反而增加了複雜度

面向物件程式設計的本質,就是使用不同的物件來完成程式

面向物件思想中最核心的概念就是 類與物件

 

3.類與物件

什麼是物件?
一切皆物件
物件指的是,具備某些特徵與技能的結合體,是實實在在存在的具體物體(描述完我就能找到它)

什麼是類?
類就是型別,類別,分類
類是一個抽象概念,不是實際存在的,是根據一些具備相同特徵和技能的物件抽取得到的,比如說人類.類的作用是用於標識物件與物件之間的差異,通過類就能大致瞭解一個物件的特徵和行為

類與物件之間的關係
類包含了一系列相同特徵和技能的物件
物件是屬於某個類的例項

先有類還是先有物件?
在生活中是先有物件再根據物件的特徵和技能 得到一個型別
在程式中先有類還是先有物件
程式設計師在程式中相當於上帝 需要什麼就創造什麼
先有類 才能通過類來產生物件,要先確定物件具備什麼特徵和什麼行為才能產生物件

在計算機建立一個人類物件
要得到物件,必須先告訴計算機,這個物件具備什麼特徵和行為,所以需要先定義類
class Person: #注類名要按照大駝峰的方式來書寫 ThisIsPerson 每個單詞的首字母都大寫

  name='herny'
  age='29'
  sex='man' #在類中描述物件的特徵和行為

obj=Person() #得到物件 通過呼叫類 ,也稱之為例項化 或 建立物件
print(obj)
# 結果:<__main__.Person object at 0x00000279452B7C50>
# 模組名為main 其包含一個Person類 通過Person類產生了一個物件 地址為0x00000279452B7C50
# 這是一個Person類的物件 其地址為0x00000279452B7C50

print(obj.name)
print(obj.age)
print(obj.sex) # 使用物件的屬性(說的就是特徵)


# 儲存屬性的位置有兩個 一個是類中,還有一個物件中
# 當每個物件的某個特徵都相同時則放到類中
# 當每個物件的某個特徵都不同時則放到物件中
class Student:
  school='Marquette'
  number='3'
  name='Wade'
  sex='man'
  age='36'
# 建立了兩個學生物件
stu1=Student()
stu2=Student()

# 每個物件記憶體地址都是不同的 , 在建立物件時,計算機會申請一個新的記憶體空間,並將物件中的內容存進去
print(stu1)
print(stu2)

# 由於name的值是宣告在類中的,所以每個物件使用的都是同一個值
print(stu1.name)
print(stu2.name)

# 為物件單獨制定屬性
stu1.name='James'
stu2.name='Bosh'
print(stu1.name)
print(stu2.name)

# 通過__dict__可以獲取一個物件中包含的內容
print(stu1.__dict__)
print(stu2.__dict__)

# 獲取類中包含的內容
print(Student.__dict__)

 

4.python建立類和物件

在計算機建立一個人類物件
要得到物件,必須先告訴計算機,這個物件具備什麼特徵和行為,所以需要先定義類
class Person: #注類名要按照大駝峰的方式來書寫 ThisIsPerson 每個單詞的首字母都大寫

  name='herny'
  age='29'
  sex='man' #在類中描述物件的特徵和行為

obj=Person() #得到物件 通過呼叫類 ,也稱之為例項化 或 建立物件
print(obj)
# 結果:<__main__.Person object at 0x00000279452B7C50>
# 模組名為main 其包含一個Person類 通過Person類產生了一個物件 地址為0x00000279452B7C50
# 這是一個Person類的物件 其地址為0x00000279452B7C50

print(obj.name)
print(obj.age)
print(obj.sex) # 使用物件的屬性(說的就是特徵)


# 儲存屬性的位置有兩個 一個是類中,還有一個物件中
# 當每個物件的某個特徵都相同時則放到類中
# 當每個物件的某個特徵都不同時則放到物件中
class Student:
  school='Marquette'
  number='3'
  name='Wade'
  sex='man'
  age='36'
# 建立了兩個學生物件
stu1=Student()
stu2=Student()

# 每個物件記憶體地址都是不同的 , 在建立物件時,計算機會申請一個新的記憶體空間,並將物件中的內容存進去
print(stu1)
print(stu2)

# 由於name的值是宣告在類中的,所以每個物件使用的都是同一個值
print(stu1.name)
print(stu2.name)

# 為物件單獨制定屬性
stu1.name='James'
stu2.name='Bosh'
print(stu1.name)
print(stu2.name)

# 通過__dict__可以獲取一個物件中包含的內容
print(stu1.__dict__)
print(stu2.__dict__)

# 獲取類中包含的內容
print(Student.__dict__)

 

5.屬性的查詢順序

"屬性的訪問順序"
1.當物件中不存在這個屬性時會到類中去找
2.如果物件中存在這個屬性,優先訪問物件中的屬性
查詢順序為 物件 -> 類
class Student:
  name='Wade'
  age='18'
  sex='man'
stu1=Student()
print(stu1.name)
stu1這個物件中沒有資料,就回到類Student裡面去找.
結果:Wade

class Student:
  name='Wade'
  age='18'
  sex='man'
stu1=Student()
stu1.name='James'
print(stu1.name)
物件中存在這個屬性,所以直接取物件中的資料
結果:James

當建立一個類的時候 會產生名稱空間,儲存類中名稱和值的繫結關係
當建立一個物件的時候 會產生名稱空間,儲存物件中名稱和值的繫結關係
類還有另一個作用 就是 作為物件的模板,所有屬於同一個類的物件,都具備類中的公共內容

即使我們什麼都不寫 類中也存在一些自帶的屬性,是從父類得到的(繼承會詳細討論)

6,初始化函式

class Student:
  pass
stu1=Student()
stu2=Student()
#指定屬性
stu1.name='Wade'
stu1.age='36'
stu1.sex='man'

stu2.name='Wendy'
stu2.age='24'
stu2.sex='woman'

print(stu1.name)
print(stu2.age)
有上述方法太繁瑣,於是我們建立函式來解決,建立這個函式目的是用於設定物件的屬性 ,如果沒有物件則該函式沒有存在的意義,也就是初始化函式與類應該是一個整體,應該講這個函式放到類中.
class Student():
  def msg(obj,name,age,sex):
    obj.name=name
    obj.age=age
    obj.sex=sex
stu1=Student()
Student.msg(stu1,'Wade',36,'man')
print(stu1.name)

現在已經簡化了程式碼 但是物件的建立和初始化步驟是分開的, 通常物件一旦建立 就應該進行初始化,所以最好時將建立與初始化進繫結
作為一個人 一旦出生 性別必須要指定
# 帶有__開頭__結尾的函式 是一些特殊內建函式,會在某個時間點自動觸發執行
class Person:
# 初始化函式名稱是固定 該函式會在呼叫類是時自動執行,self引數必須有,表示要進行初始化的物件,系統會自動傳值
def __init__(self,name,age):
  print('執行了__init__')
  print(self)
  self.name=name
  self.age=age
p1=Person('henry',29)
print(p1.__dict__)
# init 函式用於初始化物件,它會在建立物件時,自動執行,並傳入呼叫類時傳遞的引數,第一個引數表示要初始化的物件本身.
# self(第一個)引數不需要手動傳遞
# self表示物件自己 是一個形式引數,名字可以隨便取,但是不建議修改


小練習: 有一個Dog類 每一個Dog物件都應該會叫 會跑 請用面向物件來完成
class Dog():
  def __init__(self,dogname,gender,age):
    self.dogname=dogname
    self.gender=gender
    self.age=age
  def call(self):
    print('你們聽%s又叫了'%self.dogname)
  def run(self):
    print('你們看%s又跑了'%self.dogname)

dog1=Dog('皮皮','公','3')
dog2=Dog('科科','母','2')
dog1.run()
dog2.call()

 

7.物件繫結方法與非繫結方法

1.繫結方法是什麼?
  什麼是繫結 把兩個東西捆綁在一起
  什麼是方法 方法 就是 函式
  函式是專業術語,不好理解,面向物件程式設計思想,是要我們模仿現實生活中的抽象概念,為了方便理解就把函式稱之為方法.
  繫結方法就是 把物件與函式進行繫結
  物件本質上就是一種存放資料的容器
  函式是用於處理資料的程式碼
  繫結方法就是將資料與處理資料的函式繫結在一起

2.為什麼要把把物件與函式進行繫結?
name = "henry"
age = 29
sex = "男"

name2 = "wendy"
age2 = 24
sex2 = "女"

def show_info(name,age,sex):
  print("hello i am %s my age:%s my sex:%s" % (name,age,sex))
show_info(name2,sex2,age2)
show_info(name,sex,age)

第一個問題傳遞引數,必須手動傳遞,很有可能傳參順序而發生錯誤
第二個問題每次處理資料 都需要手動傳引數
第三個問題 當要處理的資料特別的多 就不能再定義為變量了 你可以使用列表出來儲存要處理的資料
但是 每次處理 都需要先獲取資料 在傳遞給處理資料的函式
所以將 要處理的資料與 處理資料的函式進行繫結
呼叫函式 就變成了呼叫物件的方法

預設情況下 在類中定義的函式都是繫結方法,共同點是,都會將物件作為第一個引數self
class Student:
  school = "BeiJing"

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

  def learning(self):
    print("正在學習..")

  def sayHI(self):
    print("hello my name is %s my age:%s my sex:%s" %(self.name,self.age,self.sex))
stu1 = Student("zion","man",18)
stu1.sayHI()
當用用物件來呼叫類中的方法時,預設把物件傳入方法中

Student.sayHI(stu1)
而用類名來呼叫時,則需要手動傳入物件

只要拿到物件 就同時拿到了資料和處理資料的方法

3.繫結方法分為兩種 一種是繫結給物件的,一種繫結給類的
class Student:
  school = "beijing"

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

繫結給類的:
繫結給類的方法使用一個裝飾器叫classmethod,必須有一個引數,表示當前類,引數名也可以自己定義,建議不要修改
@classmethod
def print_school_name(cls): # 輸出類裡面叫school的屬性
  print(cls.school)
繫結給物件的:
def say_hi(self):
  print(self.name, " 說: 你好")

Student.school_msg()
#類的繫結方法,物件和類都能呼叫,並且都會自動傳入這個類

stu1=Student('irene','27','woman')
Student.say_hi(stu1)
# 物件繫結方法 可以使用物件來呼叫 也可以使用類名來呼叫
# 在物件呼叫時會自動傳入物件自己
# 類呼叫時不會自動傳參

一個方法到底應該繫結給物件還是繫結給類?
當要處理的資料包含在類中時,就應該繫結給類
當要處理的資料包含在物件中時,就應該繫結給物件

總結:
"""
# 類的繫結方法和物件的繫結方法的相同與不同
相同點:
  1.都會自動傳值
  2.都可以被類和物件呼叫

不同點:
  1.物件繫結方法再物件呼叫時 傳的是物件自己 而類繫結方法字自動傳的是類自己
  2.第一個引數 個cls 一個叫self

為什麼要繫結?
# 第一個問題傳遞引數,必須手動傳遞,很有可能傳參順序而發生錯誤
# 第二個問題每次處理資料 都需要手動傳引數
# 第三個問題 當要處理的資料特別的多 就不能再定義為變量了 你可以使用列表出來儲存要處理的資料
但是 每次處理 都需要先獲取資料 在傳遞給處理資料的函式
之所以繫結 ,簡化程式碼,提高效率

class Teacher:

  def __init__(self,name,sex):
    self.name = name
    self.sex = sex

  # @staticmethod 用於定義個非繫結方法
  @staticmethod
  def test_func(num):
    print("test_func run!")
    print(num)

Teacher.test_func(1)

t1 = Teacher("wendy","woman")
t1.test_func(100)
print(t1.test_func)


# 什麼是非繫結方法 在類中 即不繫結給類 也不繫結給物件
# 特點:沒有自動傳引數的效果 ,類和物件向都能呼叫,就是一個普通函式
# 當你的這個功能不需要訪問類的資料 也不需要訪問物件的資料,就可以作為一個非繫結方法
# 使用場景較少

小練習:
1.建立Student類
2.擁有以下屬性: 姓名 性別 年齡 學校 班級
3.擁有以下方法
save(name) 其作用是將這個物件序列化到檔案中
get_obj(name) 其作用是根據name從檔案中反序列化為得到一個物件
分析save方法和get_obj 應該作為繫結給物件還是繫結給類

import json
class Student:
  school='pking'
  def __init__(self,name,sex,age,classes):
    self.name=name
    self.sex=sex
    self.age=age
    self.classes=classes
  def save(self):
    dic={'name':self.name,'age':self.age,'sex':self.sex,'classes':self.classes}
    with open(self.name,'wt',encoding='utf-8') as f:
      json.dump(dic,f)
  @classmethod
  def get_obj(cls,name):
    with open(name,'rt',encoding='utf-8') as f:
      dic=json.load(f)
    obj=cls(dic['name'],dic['sex'],dic['age'],dic['classes'])
    return obj
# stu1=Student('henry','man','29','python五期')
# stu1.save()
stu1=Student.get_obj('henry')
print(stu1.name)