亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在Python中使用多態

發布時間:2021-05-26 09:42:53 來源:億速云 閱讀:204 作者:Leah 欄目:開發技術

這篇文章將為大家詳細講解有關如何在Python中使用多態,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

多態

1、多態使用

一種事物的多種體現形式,舉例:動物有很多種

注意: 繼承是多態的前提

函數重寫就是多態的體現形式

演示:重寫Animal類

第一步:先定義貓類和老鼠類,繼承自object,在其中書寫構造方法和eat方法
第二步: 抽取Animal父類,定義屬性和eat方法,貓類與老鼠類繼承即可
第三步: 定義人類,在其中分別定義喂貓和喂老鼠的方法
第四步:使用多態,將多個喂的方法提取一個。

# 測試類
from cat import Cat
from mouse import Mouse
from person import Person
'''
多態: 一種事物的多種狀態
需求:人可以喂任何一種動物
'''
#創建貓和老鼠的對象
tom = Cat("tom")
jerry = Mouse("jerry")
#調用各自的方法
tom.eat()
jerry.eat()
#定義了一個有name屬性和eat方法的Animal類,讓所有的動物類都繼承自Animal.
#定義一個人類,可以喂貓和老鼠吃東西
per = Person()
#per.feedCat(tom)
#per.feedMouse(jerry)
#思考:人要喂100種動物,難道要寫100個feed方法嗎?
#前提:tom和jerry都繼承自動物
per.feedAnimal(tom)
per.feedAnimal(jerry)

輸出:

tom吃
jerry吃
給你食物
tom吃
給你食物
jerry吃

#animal.py文件中的動物類
class Animal(object):
  def __init__(self, name):
    self.name = name
  def eat(self):
    print(self.name + "吃")
#cat.py文件中的貓類
class Cat(Animal):
  def __init__(self, name):
    #self.name = name
    super(Cat,self).__init__(name)
#mouse.py中的老鼠類
class Mouse(Animal):
  def __init__(self, name):
    #self.name = name
    super(Mouse,self).__init__(name)
#person.py中的人類
class Person(object):
  def feedAnimal(self, ani):
    print("給你食物")
    ani.eat()

2、對象屬性與類屬性

對象屬性和類屬性的區別:

a.定義的位置不同,類屬性是直接在類中的屬性,對象屬性是在定義在構造方法中的屬性;

b.對象屬性使用對象訪問,類屬性使用類名訪問;

c.在內存中出現的時機不同[類屬性隨著類的加載而出現,對象屬性隨著對象的創建而出現];

d.優先級不同,對象屬性的優先級高于類屬性。

class Person(object):
  #1.定義位置
  #類屬性:直接定義在類中的屬性
  name = "person"
  def __init__(self, name):
    #對象屬性:定義在構造方法中的屬性
    self.name = name
#2.訪問方式
print(Person.name)
per = Person("tom")
#對象屬性的優先級高于類屬性
print(per.name)
#動態的給對象添加對象屬性
per.age = 18
#只針對當前對象生效,對于類創建的其他對象沒有作用
print(Person.name)
per2 = Person("lilei")
#print(per2.age) #沒有age屬性
#刪除對象中的name屬性,再調用會使用到同名的類屬性
del per.name
print(per.name)
#注意事項:不要將對象屬性與類屬性重名,因為對象屬性會屏蔽掉類屬性,但是當刪除對象屬性之后,再使用就能使用到類屬性了.

輸出:

person
tom
person
person

3、動態添加屬性和方法

正常情況下,我們定義了一個class,創建一個class的實例后,我們可以給該實例綁定任何的的屬性和方法,這就是動態語言的靈活性。

python語言的特點:靈活。

這里說的動態添加屬性和方法主要指的是關于slots函數的使用

from types import MethodType
#定義一個空類
'''
class Person():
  pass
'''
class Person(object):
  __slots__ = ("name","age","speak","hobby")
  pass
# 動態添加屬性[體現了動態語言的特點:靈活性]
per = Person()
per.name = "tom"
print(per.name)
#動態添加方法
def say(self):
  print("my name is "+ self.name)
per.speak = say
per.speak(per)
#這樣實現不好,所以引入MethodType
def hobby(self):
  print("my hobby is running")
per.hobby = MethodType(hobby,per)
per.hobby()

輸出:

tom
my name is tom
my hobby is running

但是,給一個實例綁定的方法對另外一個實例是不起作用的。

為了給所有的實例都綁定方法,可以通過給class綁定方法

#動態添加方法
def say(self,name):
  self.name = name
  print("my name is "+ self.name)
Person.speak = say
per2 = Person()
per2.speak('hh')

輸出:

my name is hh

給class綁定方法后,所有的實例均可調用。

4、slots

通常情況下,上面的say方法可以直接定義在class中,但動態綁定允許我們在程序在運行的過程中動態的給class添加功能,這在靜態語言中很難實現。

如果我們想限制實例的屬性怎么辦?

比如,只允許給Person實例添加name,age屬性,為了達到限制的目的,Python中允許在定義class的時候,定義一個特殊的變量【slots】變量,來限制該class添加的屬性

class Person(object):
  __slots__=("name","age")
#[不想無限制的任意添加屬性]
#比如,只允許給對象添加name, age屬性
#解決:定義類的時候,定義一個特殊的屬性(__slots__),可以限制動態添加的屬性范圍
per = Person()
per.height = 170
print(per.height)

這樣做會報錯

AttributeError: 'Person' object has no attribute 'height'

使用slots的時候需要注意,slots定義的屬性僅僅對當前類的實例起作用,對繼承的子類是不起作用的。

除非在子類中也定義slots,這樣子類實例允許定義的屬性就是自身的slots加上父類的slots。

總結:

__slots__:

語法:

__slots__ = (屬性名1,屬性名2,...)

作用:

限制類的屬性名

注意:當子類沒有添加slots時,子類繼承父類的時候,它的屬性名不受父類的影響

若子類中也添加slots,子類的限制應該是父類的slots與子類slots的并集

5、@property

綁定屬性時,如果我們直接把屬性暴露出去,雖然寫起來簡單,但是沒有辦法檢查參數,導致可以隨意的更改。

比如:

p = Person()
p.age = -1

這顯然不合常理,為了限制age的范圍,我們可以通過setAge()的方法來設置age,再通過getAge()的方法獲取age,這樣在setAge()中就可以檢查輸入的參數的合理性了。

class Person(object):
  def __init__(self, name, age):
    # 屬性直接對外暴露
    # self.age = age
    # 限制訪問
    self.__age = age
    self.__name = name
    # self.__name = name
  def getAge(self):
    return self.__age
  def setAge(self, age):
    if age < 0:
      age = 0
    self.__age = age
  # 通過@property和@age.setter改變原來的get/set方法
  # 方法名為受限制的變量去掉雙下劃線
  # 相當于get方法
  @property
  def age(self):
    return self.__age
  # 相當于set的方法
  @age.setter # 去掉下劃線.setter
  def age(self, age):
    if age < 0:
      age = 0
    self.__age = age
  @property
  def name(self):
    return self.__name
  @name.setter
  def name(self, name):
    self.__name = name
per = Person("lili", 18)
# 屬性直接對外暴露
# 不安全,沒有數據的過濾
# per.age = -10
# print(per.age)
# 使用限制訪問,需要自己寫set和get的方法才能訪問
# 劣勢:麻煩,代碼不直觀
# 思考問題:如果我就想使用對象"."的方式訪問對象的私有屬性,怎么辦?
# per.setAge(15)
# print(per.getAge())
# property:可以讓你對受限制訪問的屬性使用"."語法
per.age = 80 # 相當于調用setAge
print(per.age) # 相當于調用getAge
print(per.name)

輸出:

80
lili

property

總結語法:

針對私有化的屬性添加的。

@property
  def 屬性名(self):
    return self.__屬性名
@屬性名.setter
  def 屬性名(self, 值):
    #業務邏輯處理
    self.屬性名 = 值

總結:

a.裝飾器(decorator)可以給函數動態加上功能,對于類的方法,裝飾器一樣起作用,python內置的@property裝飾器就是負責把一個方法變成屬性調用的。
b.@property的實現比較復雜,我們先考慮如何使用,把一個getter方法變成屬性,只需要加上@property就可以了,此時@property本身又創建了另一個裝飾器@屬性setter,負責把一個setter方法變成屬性賦值.
c.@property廣泛應用在類的定義中,可以讓調用者寫出簡短的代碼,同時保證對參數進行必要的檢查,這樣,程序運行時就減少了出錯的可能性。

6、運算符重載

類可以重載加減運算,打印,函數調用,索引等內置運算,運算符重載使我們的對象的行為與內置函數一樣,在python調用時操作符會自動的作用于類的對象,python會自動的搜索并調用對象中指定的方法完成操作。

1、常見運算符重載方法

常見運算符重載方法

方法名重載說明運算符調用方式
init構造函數對象創建: X = Class(args)
del析構函數X對象收回
add sub加減運算X+Y, X+=Y/X-Y, X-=Y
or運算符|X|Y, X|=Y
str_ repr打印/轉換print(X)、repr(X)/str(X)
call函數調用X(*args, **kwargs)
getattr屬性引用X.undefined
setattr屬性賦值X.any=value
delattr屬性刪除del X.any
getattribute屬性獲取X.any
getitem索引運算X[key],X[i:j]
setitem索引賦值X[key],X[i:j]=sequence
delitem索引和分片刪除del X[key],del X[i:j]
len長度len(X)
bool布爾測試bool(X)
lt gt le ge eq ne特定的比較依次為XY,X<=Y,X>=Y, X==Y,X!=Y 注釋:(lt: less than, gt: greater than, le: less equal, ge: greater equal, eq: equal, ne: not equal )
radd右側加法other+X
iadd實地(增強的)加法X+=Y(or else add)
iter next迭代I=iter(X), next()
contains成員關系測試item in X(X為任何可迭代對象)
index整數值hex(X), bin(X), oct(X)
enter exit環境管理器with obj as var:
get set delete描述符屬性X.attr, X.attr=value, del X.attr
new創建在init之前創建對象
# 舉例
# 數字和字符串都能相加
#print(1 + 2)
#print("1" + "2")
# 不同的類型用加法會有不同的解釋
class Person(object):
  def __init__(self, num):
    self.num = num
  # 運算符重載
  def __add__(self, other):
    return Person(self.num + other.num)
  # 方法重寫
  def __str__(self):
    return "num = " + str(self.num)
# 如果兩個對象相加會怎樣?
# 對象相加,編譯器解釋不了,所以就要用到運算符重載
per1 = Person(1)
per2 = Person(2)
print(per1 + per2)
# 結果為地址:per1+per2 === per1.__add__(per2),如果想得到num的和則重寫str方法
# 上述打印就等價于:print(per1.__add__(per2)),只不過add方法會自動調用
print(per1)
print(per2)

輸出:

num = 3
num = 1
num = 2

python的數據類型有哪些?

python的數據類型:1. 數字類型,包括int(整型)、long(長整型)和float(浮點型)。2.字符串,分別是str類型和unicode類型。3.布爾型,Python布爾類型也是用于邏輯運算,有兩個值:True(真)和False(假)。4.列表,列表是Python中使用最頻繁的數據類型,集合中可以放任何數據類型。5. 元組,元組用”()”標識,內部元素用逗號隔開。6. 字典,字典是一種鍵值對的集合。7. 集合,集合是一個無序的、不重復的數據組合。

關于如何在Python中使用多態就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金堂县| 奉节县| 阳朔县| 宁阳县| 吴忠市| 三门峡市| 兰西县| 沂源县| 成安县| 罗田县| 隆化县| 新兴县| 吴桥县| 陆河县| 柳江县| 德格县| 巩留县| 陈巴尔虎旗| 凤山县| 竹山县| 珠海市| 德清县| 临江市| 长海县| 高邑县| 海淀区| 石林| 基隆市| 江陵县| 怀安县| 石泉县| 泸水县| 三穗县| 疏附县| 卢氏县| 西平县| 郸城县| 四平市| 增城市| 仪征市| 乃东县|