1. 程式人生 > >面向物件的繫結方法

面向物件的繫結方法

初始化函式

  • 指定物件的值:

class Student:
  pass

#指定屬性
stu1 = Student()
stu1.name = '張無忌'
stu1.sex = 'man'
stu1.age = 18
#指定屬性
stu2 = Student()
stu2.name = '周芷若'
stu2.sex = 'woman'
stu2.age = 18
  • 但是,如果有1000個學生,怎麼優化寫法?

定義函式,用於為物件設定屬性:

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

set_attr(stu3,'趙敏','woman',18)
print(stu3.__dict__)
#輸出內容 : {'name': '趙敏', 'sex': 'woman', 'age': 18}

 

把函式放到類中就是一個初始化函式
  • 初始化函式應該和類是一個整體

  • set_attr() 這個函式的目的用於設定物件的屬性,如果沒有物件此函式則沒有存在的意義

新的呼叫方式:

class Student:
  def set_attr(obj, name, sex, age):
      obj.name = name
      obj.sex = sex
      obj.age = age
```

#新的呼叫方式
stu3 = Student()
Student.set_attr(stu3,'趙敏','woman',18)
print(stu3.__dict__)
  • 但是,物件與初始化函式是分開的,可以建立物件,而不必執行函式

通常物件一旦被建立,初始化函式就會執行,物件與初始化函式通常是繫結關係:

示範1:

class Student:
  #初始化函式名稱是固定的,__開頭__結尾的函式,會在某些時機下自動觸發執行
  def __init__(self):
      print('執行了__init__')
      print(self)
      pass

s1 = Student()
#__init__在類的呼叫是就會執行
print(s1)
#self就是自身的意思

示範2:

class Student:
  def __init__(self):
      self.name = '張三丰'
      self.age = 78
s1 = Student()
print(s1.__dict__)
s2 = Student()
print(s2.__dict__)
#這樣寫死了,因為兩個的值是一樣的
正確的寫法:
class Student:
def __init__(self,name,age):
self.name = name 
self.age = age#固定的寫法,self可以自定義,但是不建議,相當於識別符號

s1 = Student('張三丰',78)
print(s1.__dict__)
s2 = Student('金庸',68)
print(s2.__dict__)
總結:
  • init函式用於初始化物件,它在建立物件時,就會自動執行:

  • 並傳入呼叫類時傳遞的引數,self作為第一個引數沒有意義,固定寫法,識別符號

 

練習:

class Phone:
  def __init__(self,p_type,price,country):
      self.p_type = p_type
      self.p_price = price
      self.country = country

p1 = Phone('iphone','5800','American')
print(p1.__dict__)

 

繫結方法

  • 繫結方法有類的繫結,物件的繫結,

  • 繫結方法可以理解為繫結函式,有繫結類的方法,繫結物件的方法,以及非繫結方法

  • 在面向物件程式設計思想中,就是要求我們模仿現實生活中的抽象概念,因此把函式稱之為方法

  • 為什麼要繫結?

  • 呼叫函式,即處理與函式繫結在那個在一起的資料,即會返回物件

  • 而物件本質上就是一種存放資料的容器

  • 所以就相當於把資料和函式繫結在一起

  • 為什麼要把資料和函式繫結在一起?

  • 得到物件,就得到了資料和處理資料的方法,就相當於執行了我們一個希望執行到的功能完整的函式.

我們實現一個循序漸進的過程:

處理一份資料:

name = '張三'
age = 20
sex = 'man'

def show_info():
  print('hello,i am %s my age is %s my sex %s'%(name,age,sex))
show_info()

把資料引用到一個函式裡面,完成對其的呼叫或處理

如果繼續重複這樣的資料,我們需要重新定義變數的值,可以優化為傳參的形式:


def show_info(name,age,sex):
  print('hello,i am %s my age is %s my sex %s'%(name,age,sex))
show_info(name,age,sex)
name = '張三'
age = 20
sex = 'man'

 

但是,傳參的缺點如下:

  • 傳參的缺點在於如果引數的傳遞形式或者格式有誤,報錯

  • 另一方面如果傳入的引數較多,費時費力,解決辦法的一種方式是把資料裝到容器裡

  • 但是每次處理都要需要先獲取資料,然後再傳遞給函式,依然比較容易出錯

  • 而且資料和函式是分離的,所以

  • ** 將要處理的資料與處理資料的函式進行繫結,函式和資料就不是分離狀態了**

  • 如何繫結,就得用類和物件了

程式碼:

繫結物件
class Student:
  school = 'BeiJing'

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

  賦予某些技能(方法)
  def learning(self):
      print('正在學習...')

  賦予某些具體的技能
  def say_hi(self):
      print('hello,i am %s my age is %s my sex %s'%(self.name,self.age,self.sex) )
  預設情況下,在類中定義的方法都是繫結方法
   
stu1 = Student('李白',18,'man')
stu1.say_hi()#用物件呼叫
Student.say_hi(stu1)#用類呼叫

註釋:以物件開頭,用物件來調類中的方法(函式),預設會把物件傳入方法中,也就是self,自身的意思

以類開頭,用類來呼叫方法時,需要手動傳入物件

 

記憶體原理(可以無視):

  • print(stu1.say_hi)

    輸出 : <bound method Student.say_hi of <main.Student object at 0x000001CE452B9EF0>>

    這是一個繫結方法,本質上是Student類中的sayhi函式,現在把這個函式繫結給記憶體中地址為0x000001CE452B9EF0的物件

  • 只要拿到物件,就同時拿到了資料和處理資料的方法,這就是之所以繫結的原因

  • 可以更有效和更有效率的處理資料
  • 以上是繫結給物件的方法,預設是繫結物件的
  • 繫結給物件的意思就是方法(函式)用的都是類裡面物件的內容,而不直接呼叫類
繫結類:
class Student:
  school = 'BeiJing'#school就是類裡的屬性
  def __init__(self,name,sex,age):
      self.name = name#這些就是物件的屬性
      self.sex = sex
      self.age = age
       
  (self.age_1 = age)也可以這樣寫,age_1是可變的,不過預設兩邊是一樣的
   
  這是繫結給物件的方法,只涉及物件
  def sayhello(self):
      print(self.name,'你好')
       
       
  繫結給類的方法,直接訪問類,需要一個裝飾器,預設引數變為cls,類的縮寫,固定格式
  @classmethod
  def print_school(cls):         
      print('學校名為%s'%Student.school)#訪問類中叫school的屬性
      print(cls.school)    
       
  def sayhello(self):
      print(self.school) # 這樣也可以操作,但是要用物件去掉,違背初衷,且太過於麻煩

Student.print_school()#類的呼叫

s1 = Student('name','sex','age')
s1.sayhello()#物件的呼叫

解釋:

  • 不加裝飾器,正常呼叫不需要傳入引數,就像訪問普通函式一樣,

  • 但是函式需要一個引數,這是類中方法的固定用法,因此不可避免要報錯。

  • 引入@classmethod裝飾器,固定用法,cls表示類,縮寫

     

      • 明確兩點

      如何定義物件繫結方法,以及類的繫結方法:

      繫結物件是用於調取物件(非類裡)屬性的方法,繫結類是調取類的屬性

      在呼叫時有何區別

      繫結類要加@classmethod裝飾器

      • 思考,一個方法在什麼場景下會繫結物件或者類?

        當要處理的資料包含在類裡時,就不能繫結給物件,應該直接繫結給類

        當要處理的資料包含在物件裡時,就應該直接繫結給物件

非繫結方法
class Teacher:
  def __init__(self,name,sex):
      self.name = name
      self.sex = sex

  @staticmethod #靜態方法,用於定義一個非繫結方法
  def test_func():       #也可以傳參
      print('test_func, run!')
Teacher.test_func()         #類訪問
t1 = Teacher('name','fun')
t1.test_func()             #物件訪問

非繫結方法,在類中定義,既不繫結給類,也不繫結給物件 特點: 沒有自動傳參的效果,誰都可以呼叫,就是一個普通函式 使用場景,這個功能不需要訪問類和物件的資料

 

練習

1.建立Student類

2.擁有以下屬性: 姓名 性別 年齡 學校 班級

3.擁有以下方法

  • save(name) 其作用是將這個物件序列化到檔案中

  • get_obj(name) 其作用是根據name從檔案中反序列化為得到一個物件

  • 分析save方法和get_obj 應該作為繫結給物件還是繫結給類

import json

class Student:

  school = "beijing"

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


  def save(self):
      dic = {"name":self.name,"sex":self.sex,
              "age":self.age,"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("阿爾法","man",20,"py5期")
# stu2 = Student("張三","woman",20,"py5期")


# stu1.save()
# stu2.save()

stu = Student.get_obj("阿爾法")
print(stu)
print(stu.name)

 

總結

類和物件的繫結方法的總結

1,相同點 都會自動傳值 都可以被類和物件呼叫 引數名都可以被修改,但是不建議修改 2,不同點 物件繫結方法在物件呼叫時,傳的是物件自己,而類繫結方法自動傳的是類自己 第一個引數不一樣,一個是self , 一個是cls

 

 

 

 

個人總結

訪問順序:

物件 ------> 類

呼叫方式:

1,物件呼叫

以物件開頭的呼叫方式,物件要先定義物件,因此要用物件傳參

2,類的呼叫

以類的名字開頭的呼叫方式,不用提前定義

初始化函式:

以init為標誌的函式,通常直接與方法繫結,方法直接呼叫其內定義的屬性

繫結方法:

1,物件的繫結

物件的繫結就是方法中,引數是初始化函式定義中的屬性,函式的結果或返回值就是物件

2,類的繫結

類的繫結就是方法中,直接呼叫初始化函式之外的屬性,要加一個裝飾器@classmethod

繫結的情景:

1,物件的繫結

屬性在物件裡,就不需要繫結給類,多此一舉

2,類的繫結

屬性包含在類裡,直接繫結給類

非繫結方法:

在類中定義,既不繫結給類,也不繫結給物件

 

已解決

類的公共內容是什麼?

是類裡所有物件共有的屬性,也即是初始化函式之外的內容,一般寫在初始化函式上面

物件跟類是什麼關係?

物件是使用類裡某些屬性和方法的東西,例項化的內容,從類裡創建出來的內容

呼叫類會產生物件,返回的是物件

初始化函式外的屬性是不是叫類裡的屬性?

不止是之外的屬性,類裡的所有東西都是一種屬性,方法也是一種屬性,萬物皆物件,萬物皆屬性

方法是函式,也是物件的技能,也是一種屬性.

怎麼區分處理的資料是在物件裡還是類裡?

區分物件屬性和類裡屬性 : 共有的是類的屬性,傳參的是物件的屬性.

物件裡是作為屬性返回的,類是是共有的屬性

物件的屬性和技能?

屬性是類似於你的名字,身高,體重,年齡,技能就類似於你使用的python

物件的屬性和技能就是呼叫類裡屬性和方法返回的值.