Python類的定義繼承調(diào)用比較方法技巧
一、類的約束
# _開頭: 私有變量; # __開問: 私有變量,不能被繼承; # __xxx__: 能被訪問,不能被繼承; class A: def __init__(self): self._internal = 0 # 私有變量不能被訪問 self.public = 1 # 可被訪問 def public_method(self): pass def _private_method(self): # 私有方法不能被訪問 pass class B: def __init__(self): self.__private = 0 # 這個屬性會在內(nèi)存中被重新命名為_B__private def __private_method(self): # 不能被訪問,不能被繼承 pass def __private_method__(self): # 能被訪問,不能被繼承 pass
二、類的定義
2.1、創(chuàng)建創(chuàng)建
class Dog: a = "0"; #相當(dāng)于public static變量,全局的 """__init__是一個默認(rèn)的方法,且self為默認(rèn)的,用self修飾的屬性為public類型的類變量""" def __init__(self, name, age): self.name = name self.age = age self.sex = "1";#設(shè)置屬性默認(rèn)值 def sit(self): print(self.name + "is now sitting" + "and sex is " + self.sex + Dog.a) @classmethod def user_name(cls, name): #注意這種注解的用法 return cls() dog = Dog("kk", 12); dog.sit()
2.1.1、類的導(dǎo)入
在python中分為文件、模塊、類,其中文件和模塊可劃等價(jià);所以導(dǎo)入有幾種方式,比如dog.py文件中定義了兩個Class,則在使用類中導(dǎo)入方法有以下幾種:
- from car import Dog;#導(dǎo)入一個模塊中的特定類,使用時(shí)則直接Car();
- import car;#導(dǎo)入一個模塊中的所有類,使用時(shí)則需要car.Car();
- from car import *;#不推薦,容易引起命名沖突問題
from collections import OrderedDict; #使用標(biāo)準(zhǔn)類庫 t = OrderedDict();
2.1.2、構(gòu)造器
class Date: # Primary constructor def __init__(self, year, month, day): self.year = year self.month = month self.day = day # Alternate constructor @classmethod def today(cls): t = time.localtime() #它接收一個class作為第一個參數(shù),它被用來創(chuàng)建并返回最終的實(shí)例, 這個cls==__init__ return cls(t.tm_year, t.tm_mon, t.tm_mday) a = Date(2020, 5, 10) # Primary b = Date.today() # Alternate
減少構(gòu)造函數(shù)的參數(shù)個數(shù):
class Structure1: # Class variable that specifies expected fields _field_list = [] def __init__(self, *args): if len(args) != len(self._field_list): raise TypeError(f'Expected {len(self._field_list)} arguments') # Set the arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Example class definitions class Course(Structure1): # 這行只是為了一個準(zhǔn)許入判斷,沒有太多實(shí)際意思,或是一個聲明 _field_list = ['course_name', 'total_class', 'score'] c = Course('python', 30, 0.3);
關(guān)鍵字參數(shù)
class Structure2: _field_list = [] def __init__(self, *args, **kwargs): if len(args) > len(self._field_list): raise TypeError(f'Expected {len(self._field_list)} arguments') # Set all of the positional arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Set the remaining keyword arguments #是通過pop這種方式來檢查的,在長度范圍內(nèi)如果pop出錯則拋異常 for name in self._field_list[len(args):]: setattr(self, name, kwargs.pop(name)) # Check for any remaining unknown arguments if kwargs: raise TypeError(f"Invalid argument(s): {','.join(kwargs)}") # Example use class Course(Structure2): _field_list = ['course_name', 'total_class', 'score'] course_1 = Course('python', 30, 0.3) course_2 = Course('python', 30, score=0.3) course_3 = Course('python', total_class=30, score=0.3)
擴(kuò)展關(guān)鍵字參數(shù):
class Structure3: # Class variable that specifies expected fields _field_list = [] def __init__(self, *args, **kwargs): if len(args) != len(self._field_list): raise TypeError(f'Expected {len(self._field_list)} arguments') # Set the arguments for name, value in zip(self._field_list, args): setattr(self, name, value) # Set the additional arguments (if any) extra_args = kwargs.keys() - self._field_list for name in extra_args: setattr(self, name, kwargs.pop(name)) if kwargs: raise TypeError(f"Duplicate values for {','.join(kwargs)}") # Example use if __name__ == '__main__': class Course(Structure3): _field_list = ['course_name', 'total_class', 'score'] course_1 = Course('python', 30, 0.3) course_2 = Course('python', 30, 0.3, date='8/5/2020')
2.1.3、類屬性
要創(chuàng)建一個新的實(shí)例屬性,可以通過描述器的形式來定義它的功能,一個描述器就是一個實(shí)現(xiàn)了3個核心屬性訪問操作的類,分別對應(yīng)get\set\delete這三個特殊的方法。
# Descriptor attribute for an integer type-checked attribute class Integer: def __init__(self, name): self.name = name """下面三個方法只是一個更嚴(yán)格的定義,可以不需要,要使用上面的描述器,需要把描述器放入到一個class中,這樣所有對描述器的訪問都會被get/set/delete所捕獲""" def __get__(self, instance, cls): if not instance: return self else: return instance.__dict__[self.name] def __set__(self, instance, value): if not isinstance(value, int): raise TypeError('Expected an int object') instance.__dict__[self.name] = value def __delete__(self, instance): del instance.__dict__[self.name]
示例1:
class Point: """實(shí)例變量,和下面的x,y不是一回事""" x = Integer('x') y = Integer('y') def __init__(self, x, y): self.x = x self.y = y print(Point.x.name) # x point = Point(3, 5) print(f'point x = {point.x}') #3 print(f'point y = {point.y}') #5 point.y = 6 print(f'after change,point y = {point.y}') #6
三、類的繼承
ptyhon在實(shí)現(xiàn)繼承時(shí)會用一個叫MRO列表的算法實(shí)現(xiàn),它有三條規(guī)則:1、子類會先于父類;2、多個父類會根據(jù)它們在列表中的順序被檢查;3、如果對下一個類有兩個合法的選擇,則返回第一個合法的父類;
3.1、單繼承
class A: def __init__(self): self.x = 0 class B(A): def __init__(self): super().__init__() #這行需要注意,也可以不寫,但不寫時(shí)就不會調(diào)用父類的init方法 self.y = 1
3.2、多繼承
class Base: def __init__(self): print('call Base.__init__') class A(Base): def __init__(self): Base.__init__(self) print('call A.__init__') class B(Base): def __init__(self): Base.__init__(self) print('call B.__init__') """多繼承的實(shí)現(xiàn)""" class C(A,B): def __init__(self): A.__init__(self) B.__init__(self) print('call C.__init__') c = C() # call Base.__init__ # call A.__init__ # call Base.__init__ # call B.__init__ # call C.__init__
3.3、調(diào)用父類方法
class Proxy: def __init__(self, obj): self._obj = obj def __getattr__(self, name): return getattr(self._obj, name) def __setattr__(self, name, value): if name.startswith('_'): """調(diào)用父類方法""" super().__setattr__(name, value) else: setattr(self._obj, name, value) proxy = Proxy({}) proxy.__setattr__("_name", "hm")
3.4、屬性擴(kuò)展
3.4.1、完全擴(kuò)展
# 父類 class Person: def __init__(self, name): self.name = name # defined Getter function, auto to call the sign name.setter when it be build @property def name(self): return self._name # defined Setter function @name.setter def name(self, value): if not isinstance(value, str): raise TypeError('Expected a string') self._name = value # defined Deleter function @name.deleter def name(self): raise AttributeError("Can't delete attribute") """子類""" class SubPerson(Person): @property def name(self): print('Getting name') return super().name @name.setter def name(self, value): print(f'Setting name to {value}') super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self) """測試""" sub_person = SubPerson('Guido') print(f'name is: {sub_person.name}')
3.4.2、單獨(dú)擴(kuò)展
class SubPerson(Person): @Person.name.getter def name(self): print('Getting name') return super().name # or super(SubPerson, SubPerson).name.__set__(self, value) sub_p = SubPerson('Bill')
#不能用property的原因是,property其實(shí)是get、set、del函數(shù)的集合,各有各的用處。下面才是正確的擴(kuò)展方式,所以下面的代碼是不工作的 class SubPerson(Person): @property # Doesn't work def name(self): print('Getting name') return super().name #如果要用property屬性則要用下面的編碼實(shí)現(xiàn) class SubPerson(Person): @property def name(self): print('Getting name') return super().name @name.setter def name(self, value): print(f'Setting name to {value}') super(SubPerson, SubPerson).name.__set__(self, value) @name.deleter def name(self): print('Deleting name') super(SubPerson, SubPerson).name.__delete__(self)
四、類的調(diào)用
import time class Date: # Primary constructor def __init__(self, year, month, day): self.year = year self.month = month self.day = day # Alternate constructor @classmethod def today(cls): t = time.localtime() #它接收一個class作為第一個參數(shù),它被用來創(chuàng)建并返回最終的實(shí)例, 這個cls==__init__ return cls(t.tm_year, t.tm_mon, t.tm_mday)
"""普通調(diào)用""" c = Date(2010, 12, 12) """類方法在繼承中使用""" class NewDate(Date): pass c = Date.today() # Creates an instance of Date (cls=Date) d = NewDate.today() # Creates an instance of NewDate (cls=NewDate)
五、抽象類
from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, max_bytes=-1): pass @abstractmethod def write(self, data): pass """不能被實(shí)例化""" #a = IStream() class SocketStream(IStream): def read(self, max_bytes=-1): pass def write(self, data): pass """檢查""" def serialize(obj, stream): if not isinstance(stream, IStream): raise TypeError('Expected an IStream') pass
5.1、強(qiáng)制類型檢查
from abc import ABCMeta, abstractmethod class IStream(metaclass=ABCMeta): @abstractmethod def read(self, max_bytes=-1): pass @abstractmethod def write(self, data): pass import io # Register the built-in I/O classes as supporting our interface IStream.register(io.IOBase) # Open a normal file and type check f = None #open('test.txt') print(f'f object is IStream type: {isinstance(f, IStream)}') #f object is IStream type: False
六、類的比較
from functools import total_ordering class Room: def __init__(self, name, length, width): self.name = name self.length = length self.width = width self.square_feet = self.length * self.width @total_ordering class House: def __init__(self, name, style): self.name = name self.style = style self.rooms = list() @property def living_space_footage(self): return sum(r.square_feet for r in self.rooms) def add_room(self, room): self.rooms.append(room) def __str__(self): return f'{self.name}: {self.living_space_footage} square foot {self.style}' def __eq__(self, other): return self.living_space_footage == other.living_space_footage def __lt__(self, other): return self.living_space_footage < other.living_space_footage # Build a few houses, and add rooms to them h1 = House('h1', 'Cape') h1.add_room(Room('Master Bedroom', 14, 21)) h1.add_room(Room('Living Room', 18, 20)) h1.add_room(Room('Kitchen', 12, 16)) h1.add_room(Room('Office', 12, 12)) h2 = House('h2', 'Ranch') h2.add_room(Room('Master Bedroom', 14, 21)) h2.add_room(Room('Living Room', 18, 20)) h2.add_room(Room('Kitchen', 12, 16)) h3 = House('h3', 'Split') h3.add_room(Room('Master Bedroom', 14, 21)) h3.add_room(Room('Living Room', 18, 20)) h3.add_room(Room('Office', 12, 16)) h3.add_room(Room('Kitchen', 15, 17)) houses = [h1, h2, h3] print(f'Is {h1} bigger than {h2}: {h1 > h2}') print(f'Is {h2} smaller than {h3}: {h2 < h3}') print(f'Is {h2} greater than or equal to {h1}: {h2 >= h1}') print(f'Which one is biggest in houses: {max(houses)}') print(f'Which is smallest in houses: {min(houses)}') """""" # Is h1: 990 square foot Cape bigger than h2: 846 square foot Ranch: True # Is h2: 846 square foot Ranch smaller than h3: 1101 square foot Split: True # Is h2: 846 square foot Ranch greater than or equal to h1: 990 square foot Cape: False # Which one is biggest in houses: h3: 1101 square foot Split # Which is smallest in houses: h2: 846 square foot Ranch # """""" class House: def __eq__(self, other): pass def __lt__(self, other): pass # Methods created by @total_ordering __le__ = lambda self, other: self < other or self == other __gt__ = lambda self, other: not (self < other or self == other) __ge__ = lambda self, other: not (self < other) __ne__ = lambda self, other: not self == other
到此這篇關(guān)于Python類的定義繼承調(diào)用比較方法技巧的文章就介紹到這了,更多相關(guān)Python類的定義內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Pycharm中python調(diào)用另一個文件類或者函數(shù)
- Python函數(shù)調(diào)用的幾種方式(類里面,類之間,類外面)
- python中類的相互調(diào)用的實(shí)踐
- python 子類調(diào)用父類的構(gòu)造函數(shù)實(shí)例
- Python實(shí)現(xiàn)子類調(diào)用父類的初始化實(shí)例
- python 中不同包 類 方法 之間的調(diào)用詳解
- python 定義類時(shí),實(shí)現(xiàn)內(nèi)部方法的互相調(diào)用
- python調(diào)用函數(shù)、類和文件操作簡單實(shí)例總結(jié)
- 調(diào)用其他python腳本文件里面的類和方法過程解析
- Python中不同類之間調(diào)用方法的四種方式小結(jié)
相關(guān)文章
Python 作圖實(shí)現(xiàn)坐標(biāo)軸截?cái)?打斷)的效果
這篇文章主要介紹了Python 作圖實(shí)現(xiàn)坐標(biāo)軸截?cái)?打斷)的效果,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04python?列表套json字典根據(jù)相同的key篩選數(shù)據(jù)
這篇文章主要介紹了python?列表套json字典根據(jù)相同的key篩選數(shù)據(jù),文章基于python的相關(guān)資料展開詳細(xì)的內(nèi)容介紹需要的小伙伴可以參考一下2022-04-04詳解Python中數(shù)據(jù)庫管理模塊shelve和dbm的應(yīng)用
作為常用的 python 自帶數(shù)據(jù)庫管理模塊,shelve 和 dbm 都是非常方便的對象持久化存儲和檢索工具,本文將從用法、優(yōu)勢以及不同點(diǎn)等方面進(jìn)行介紹,希望對大家有所幫助2023-10-10Python Pandas實(shí)現(xiàn)DataFrame合并的圖文教程
我們在使用pandas處理數(shù)據(jù)的時(shí)候,往往會需要合并兩個或者多個DataFrame的操作,下面這篇文章主要給大家介紹了關(guān)于Pandas實(shí)現(xiàn)DataFrame合并的相關(guān)資料,需要的朋友可以參考下2022-07-07python百行代碼自制電腦端網(wǎng)速懸浮窗的實(shí)現(xiàn)
這篇文章主要介紹了python百行代碼自制電腦端網(wǎng)速懸浮窗的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Python編程functools模塊創(chuàng)建修改的高階函數(shù)解析
本篇文章主要為大家介紹functools模塊中用于創(chuàng)建、修改函數(shù)的高階函數(shù),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-09-09python中使用xlrd讀excel使用xlwt寫excel的實(shí)例代碼
這篇文章主要介紹了python中使用xlrd讀excel使用xlwt寫excel的實(shí)例代碼,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下2018-01-01