08 - Python面向對象編程進階

面向對象進階

在前面的章節我們已經了解了面向對象的入門知識,知道了如何定義類,如何創建對象以及如何給對象發消息。為了能夠更好的使用面向對象編程思想進行程序開發,我們還需要對Python中的面向對象編程進行更為深入的了解。

@property裝飾器

之前我們討論過Python中屬性和方法訪問權限的問題,雖然我們不建議將屬性設置為私有的,但是如果直接將屬性暴露給外界也是有問題的,比如我們沒有辦法檢查賦給屬性的值是否有效。我們之前的建議是將屬性命名以單下劃線開頭,通過這種方式來暗示屬性是受保護的,不建議外界直接訪問,那么如果想訪問屬性可以通過屬性的getter(訪問器)和setter(修改器)方法進行對應的操作。如果要做到這點,就可以考慮使用@property包裝器來包裝getter和setter方法,使得對屬性的訪問既安全又方便,代碼如下所示。

class Person(object):def __init__(self, name, age):self._name = nameself._age = age# 訪問器 - getter方法@propertydef name(self):return self._name# 訪問器 - getter方法@propertydef age(self):return self._age# 修改器 - setter方法@age.setterdef age(self, age):self._age = agedef play(self):if self._age <= 16:print('%s正在玩飛行棋.' % self._name)else:print('%s正在玩斗地主.' % self._name)def main():person = Person('王大錘', 12)person.play()person.age = 22person.play()# person.name = '白元芳'  # AttributeError: can't set attributeif __name__ == '__main__':main()

__slots__魔法

我們講到這里,不知道大家是否已經意識到,Python是一門動態語言。通常,動態語言允許我們在程序運行時給對象綁定新的屬性或方法,當然也可以對已經綁定的屬性和方法進行解綁定。但是如果我們需要限定自定義類型的對象只能綁定某些屬性,可以通過在類中定義__slots__變量來進行限定。需要注意的是__slots__的限定只對當前類的對象生效,對子類并不起任何作用。

class Person(object):# 限定Person對象只能綁定_name, _age和_gender屬性__slots__ = ('_name', '_age', '_gender')def __init__(self, name, age):self._name = nameself._age = age@propertydef name(self):return self._name@propertydef age(self):return self._age@age.setterdef age(self, age):self._age = agedef play(self):if self._age <= 16:print('%s正在玩飛行棋.' % self._name)else:print('%s正在玩斗地主.' % self._name)def main():person = Person('王大錘', 22)person.play()person._gender = '男'# AttributeError: 'Person' object has no attribute '_is_gay'# person._is_gay = True

靜態方法和類方法

之前,我們在類中定義的方法都是對象方法,也就是說這些方法都是發送給對象的消息。實際上,我們寫在類中的方法并不需要都是對象方法,例如我們定義一個“三角形”類,通過傳入三條邊長來構造三角形,并提供計算周長和面積的方法,但是傳入的三條邊長未必能構造出三角形對象,因此我們可以先寫一個方法來驗證三條邊長是否可以構成三角形,這個方法很顯然就不是對象方法,因為在調用這個方法時三角形對象尚未創建出來(因為都不知道三條邊能不能構成三角形),所以這個方法是屬于三角形類而并不屬于三角形對象的。我們可以使用靜態方法來解決這類問題,代碼如下所示。

from math import sqrtclass Triangle(object):def __init__(self, a, b, c):self._a = aself._b = bself._c = c@staticmethoddef is_valid(a, b, c):return a + b > c and b + c > a and a + c > bdef perimeter(self):return self._a + self._b + self._cdef area(self):half = self.perimeter() / 2return sqrt(half * (half - self._a) *(half - self._b) * (half - self._c))def main():a, b, c = 3, 4, 5# 靜態方法和類方法都是通過給類發消息來調用的if Triangle.is_valid(a, b, c):t = Triangle(a, b, c)print(t.perimeter())# 也可以通過給類發消息來調用對象方法但是要傳入接收消息的對象作為參數# print(Triangle.perimeter(t))print(t.area())# print(Triangle.area(t))else:print('無法構成三角形.')if __name__ == '__main__':main()

和靜態方法比較類似,Python還可以在類中定義類方法,類方法的第一個參數約定名為cls,它代表的是當前類相關的信息的對象(類本身也是一個對象,有的地方也稱之為類的元數據對象),通過這個參數我們可以獲取和類相關的信息并且可以創建出類的對象,代碼如下所示。

from time import time, localtime, sleepclass Clock(object):"""數字時鐘"""def __init__(self, hour=0, minute=0, second=0):self._hour = hourself._minute = minuteself._second = second@classmethoddef now(cls):ctime = localtime(time())return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)def run(self):"""走字"""self._second += 1if self._second == 60:self._second = 0self._minute += 1if self._minute == 60:self._minute = 0self._hour += 1if self._hour == 24:self._hour = 0def show(self):"""顯示時間"""return '%02d:%02d:%02d' % \(self._hour, self._minute, self._second)def main():# 通過類方法創建對象并獲取系統時間clock = Clock.now()while True:print(clock.show())sleep(1)clock.run()if __name__ == '__main__':main()

類之間的關系

簡單的說,類和類之間的關系有三種:is-a、has-a和use-a關系。

  • is-a關系也叫繼承或泛化,比如學生和人的關系、手機和電子產品的關系都屬于繼承關系。
  • has-a關系通常稱之為關聯,比如部門和員工的關系,汽車和引擎的關系都屬于關聯關系;關聯關系如果是整體和部分的關聯,那么我們稱之為聚合關系;如果整體進一步負責了部分的生命周期(整體和部分是不可分割的,同時同在也同時消亡),那么這種就是最強的關聯關系,我們稱之為合成關系。
  • use-a關系通常稱之為依賴,比如司機有一個駕駛的行為(方法),其中(的參數)使用到了汽車,那么司機和汽車的關系就是依賴關系。

我們可以使用一種叫做UML(統一建模語言)的東西來進行面向對象建模,其中一項重要的工作就是把類和類之間的關系用標準化的圖形符號描述出來。關于UML我們在這里不做詳細的介紹,有興趣的讀者可以自行閱讀《UML面向對象設計基礎》一書。

在這里插入圖片描述

在這里插入圖片描述

利用類之間的這些關系,我們可以在已有類的基礎上來完成某些操作,也可以在已有類的基礎上創建新的類,這些都是實現代碼復用的重要手段。復用現有的代碼不僅可以減少開發的工作量,也有利于代碼的管理和維護,這是我們在日常工作中都會使用到的技術手段。

繼承和多態

剛才我們提到了,可以在已有類的基礎上創建新類,這其中的一種做法就是讓一個類從另一個類那里將屬性和方法直接繼承下來,從而減少重復代碼的編寫。提供繼承信息的我們稱之為父類,也叫超類或基類;得到繼承信息的我們稱之為子類,也叫派生類或衍生類。子類除了繼承父類提供的屬性和方法,還可以定義自己特有的屬性和方法,所以子類比父類擁有的更多的能力,在實際開發中,我們經常會用子類對象去替換掉一個父類對象,這是面向對象編程中一個常見的行為,對應的原則稱之為里氏替換原則。下面我們先看一個繼承的例子。

class Person(object):"""人"""def __init__(self, name, age):self._name = nameself._age = age@propertydef name(self):return self._name@propertydef age(self):return self._age@age.setterdef age(self, age):self._age = agedef play(self):print('%s正在愉快的玩耍.' % self._name)def watch_av(self):if self._age >= 18:print('%s正在觀看愛情片.' % self._name)else:print('%s只能觀看《熊出沒》.' % self._name)class Student(Person):"""學生"""def __init__(self, name, age, grade):super().__init__(name, age)self._grade = grade@propertydef grade(self):return self._grade@grade.setterdef grade(self, grade):self._grade = gradedef study(self, course):print('%s的%s正在學習%s.' % (self._grade, self._name, course))class Teacher(Person):"""老師"""def __init__(self, name, age, title):super().__init__(name, age)self._title = title@propertydef title(self):return self._title@title.setterdef title(self, title):self._title = titledef teach(self, course):print('%s%s正在講%s.' % (self._name, self._title, course))def main():stu = Student('王大錘', 15, '初三')stu.study('數學')stu.watch_av()t = Teacher('張三', 38, '老叫獸')t.teach('Python程序設計')t.watch_av()if __name__ == '__main__':main()

子類在繼承了父類的方法后,可以對父類已有的方法給出新的實現版本,這個動作稱之為方法重寫(override)。通過方法重寫我們可以讓父類的同一個行為在子類中擁有不同的實現版本,當我們調用這個經過子類重寫的方法時,不同的子類對象會表現出不同的行為,這個就是多態(poly-morphism)。

from abc import ABCMeta, abstractmethodclass Pet(object, metaclass=ABCMeta):"""寵物"""def __init__(self, nickname):self._nickname = nickname@abstractmethoddef make_voice(self):"""發出聲音"""passclass Dog(Pet):"""狗"""def make_voice(self):print('%s: 汪汪汪...' % self._nickname)class Cat(Pet):"""貓"""def make_voice(self):print('%s: 喵...喵...' % self._nickname)def main():pets = [Dog('旺財'), Cat('凱蒂'), Dog('大黃')]for pet in pets:pet.make_voice()if __name__ == '__main__':main()

在上面的代碼中,我們將Pet類處理成了一個抽象類,所謂抽象類就是不能夠創建對象的類,這種類的存在就是專門為了讓其他類去繼承它。Python從語法層面并沒有像Java或C#那樣提供對抽象類的支持,但是我們可以通過abc模塊的ABCMeta元類和abstractmethod包裝器來達到抽象類的效果,如果一個類中存在抽象方法那么這個類就不能夠實例化(創建對象)。上面的代碼中,DogCat兩個子類分別對Pet類中的make_voice抽象方法進行了重寫并給出了不同的實現版本,當我們在main函數中調用該方法時,這個方法就表現出了多態行為(同樣的方法做了不同的事情)。

綜合案例

案例1:奧特曼打小怪獸
from abc import ABCMeta, abstractmethod
from random import randint, randrangeclass Fighter(object, metaclass=ABCMeta):"""戰斗者"""# 通過__slots__魔法限定對象可以綁定的成員變量__slots__ = ('_name', '_hp')def __init__(self, name, hp):"""初始化方法:param name: 名字:param hp: 生命值"""self._name = nameself._hp = hp@propertydef name(self):return self._name@propertydef hp(self):return self._hp@hp.setterdef hp(self, hp):self._hp = hp if hp >= 0 else 0@propertydef alive(self):return self._hp > 0@abstractmethoddef attack(self, other):"""攻擊:param other: 被攻擊的對象"""passclass Ultraman(Fighter):"""奧特曼"""__slots__ = ('_name', '_hp', '_mp')def __init__(self, name, hp, mp):"""初始化方法:param name: 名字:param hp: 生命值:param mp: 魔法值"""super().__init__(name, hp)self._mp = mpdef attack(self, other):other.hp -= randint(15, 25)def huge_attack(self, other):"""究極必殺技(打掉對方至少50點或四分之三的血):param other: 被攻擊的對象:return: 使用成功返回True否則返回False"""if self._mp >= 50:self._mp -= 50injury = other.hp * 3 // 4injury = injury if injury >= 50 else 50other.hp -= injuryreturn Trueelse:self.attack(other)return Falsedef magic_attack(self, others):"""魔法攻擊:param others: 被攻擊的群體:return: 使用魔法成功返回True否則返回False"""if self._mp >= 20:self._mp -= 20for temp in others:if temp.alive:temp.hp -= randint(10, 15)return Trueelse:return Falsedef resume(self):"""恢復魔法值"""incr_point = randint(1, 10)self._mp += incr_pointreturn incr_pointdef __str__(self):return '~~~%s奧特曼~~~\n' % self._name + \'生命值: %d\n' % self._hp + \'魔法值: %d\n' % self._mpclass Monster(Fighter):"""小怪獸"""__slots__ = ('_name', '_hp')def attack(self, other):other.hp -= randint(10, 20)def __str__(self):return '~~~%s小怪獸~~~\n' % self._name + \'生命值: %d\n' % self._hpdef is_any_alive(monsters):"""判斷有沒有小怪獸是活著的"""for monster in monsters:if monster.alive > 0:return Truereturn Falsedef select_alive_one(monsters):"""選中一只活著的小怪獸"""monsters_len = len(monsters)while True:index = randrange(monsters_len)monster = monsters[index]if monster.alive > 0:return monsterdef display_info(ultraman, monsters):"""顯示奧特曼和小怪獸的信息"""print(ultraman)for monster in monsters:print(monster, end='')def main():u = Ultraman('駱昊', 1000, 120)m1 = Monster('狄仁杰', 250)m2 = Monster('白元芳', 500)m3 = Monster('王大錘', 750)ms = [m1, m2, m3]fight_round = 1while u.alive and is_any_alive(ms):print('========第%02d回合========' % fight_round)m = select_alive_one(ms)  # 選中一只小怪獸skill = randint(1, 10)   # 通過隨機數選擇使用哪種技能if skill <= 6:  # 60%的概率使用普通攻擊print('%s使用普通攻擊打了%s.' % (u.name, m.name))u.attack(m)print('%s的魔法值恢復了%d點.' % (u.name, u.resume()))elif skill <= 9:  # 30%的概率使用魔法攻擊(可能因魔法值不足而失敗)if u.magic_attack(ms):print('%s使用了魔法攻擊.' % u.name)else:print('%s使用魔法失敗.' % u.name)else:  # 10%的概率使用究極必殺技(如果魔法值不足則使用普通攻擊)if u.huge_attack(m):print('%s使用究極必殺技虐了%s.' % (u.name, m.name))else:print('%s使用普通攻擊打了%s.' % (u.name, m.name))print('%s的魔法值恢復了%d點.' % (u.name, u.resume()))if m.alive > 0:  # 如果選中的小怪獸沒有死就回擊奧特曼print('%s回擊了%s.' % (m.name, u.name))m.attack(u)display_info(u, ms)  # 每個回合結束后顯示奧特曼和小怪獸的信息fight_round += 1print('\n========戰斗結束!========\n')if u.alive > 0:print('%s奧特曼勝利!' % u.name)else:print('小怪獸勝利!')if __name__ == '__main__':main()
案例2:撲克游戲
import randomclass Card(object):"""一張牌"""def __init__(self, suite, face):self._suite = suiteself._face = face@propertydef face(self):return self._face@propertydef suite(self):return self._suitedef __str__(self):if self._face == 1:face_str = 'A'elif self._face == 11:face_str = 'J'elif self._face == 12:face_str = 'Q'elif self._face == 13:face_str = 'K'else:face_str = str(self._face)return '%s%s' % (self._suite, face_str)def __repr__(self):return self.__str__()class Poker(object):"""一副牌"""def __init__(self):self._cards = [Card(suite, face) for suite in '????'for face in range(1, 14)]self._current = 0@propertydef cards(self):return self._cardsdef shuffle(self):"""洗牌(隨機亂序)"""self._current = 0random.shuffle(self._cards)@propertydef next(self):"""發牌"""card = self._cards[self._current]self._current += 1return card@propertydef has_next(self):"""還有沒有牌"""return self._current < len(self._cards)class Player(object):"""玩家"""def __init__(self, name):self._name = nameself._cards_on_hand = []@propertydef name(self):return self._name@propertydef cards_on_hand(self):return self._cards_on_handdef get(self, card):"""摸牌"""self._cards_on_hand.append(card)def arrange(self, card_key):"""玩家整理手上的牌"""self._cards_on_hand.sort(key=card_key)# 排序規則-先根據花色再根據點數排序
def get_key(card):return (card.suite, card.face)def main():p = Poker()p.shuffle()players = [Player('東邪'), Player('西毒'), Player('南帝'), Player('北丐')]for _ in range(13):for player in players:player.get(p.next)for player in players:print(player.name + ':', end=' ')player.arrange(get_key)print(player.cards_on_hand)if __name__ == '__main__':main()

說明:大家可以自己嘗試在上面代碼的基礎上寫一個簡單的撲克游戲,例如21點(Black Jack),游戲的規則可以自己在網上找一找。

案例3:工資結算系統
"""
某公司有三種類型的員工 分別是部門經理、程序員和銷售員
需要設計一個工資結算系統 根據提供的員工信息來計算月薪
部門經理的月薪是每月固定15000元
程序員的月薪按本月工作時間計算 每小時150元
銷售員的月薪是1200元的底薪加上銷售額5%的提成
"""
from abc import ABCMeta, abstractmethodclass Employee(object, metaclass=ABCMeta):"""員工"""def __init__(self, name):"""初始化方法:param name: 姓名"""self._name = name@propertydef name(self):return self._name@abstractmethoddef get_salary(self):"""獲得月薪:return: 月薪"""passclass Manager(Employee):"""部門經理"""def get_salary(self):return 15000.0class Programmer(Employee):"""程序員"""def __init__(self, name, working_hour=0):super().__init__(name)self._working_hour = working_hour@propertydef working_hour(self):return self._working_hour@working_hour.setterdef working_hour(self, working_hour):self._working_hour = working_hour if working_hour > 0 else 0def get_salary(self):return 150.0 * self._working_hourclass Salesman(Employee):"""銷售員"""def __init__(self, name, sales=0):super().__init__(name)self._sales = sales@propertydef sales(self):return self._sales@sales.setterdef sales(self, sales):self._sales = sales if sales > 0 else 0def get_salary(self):return 1200.0 + self._sales * 0.05def main():emps = [Manager('劉備'), Programmer('諸葛亮'),Manager('曹操'), Salesman('荀彧'),Salesman('呂布'), Programmer('張遼'),Programmer('趙云')]for emp in emps:if isinstance(emp, Programmer):emp.working_hour = int(input('請輸入%s本月工作時間: ' % emp.name))elif isinstance(emp, Salesman):emp.sales = float(input('請輸入%s本月銷售額: ' % emp.name))# 同樣是接收get_salary這個消息但是不同的員工表現出了不同的行為(多態)print('%s本月工資為: ¥%s元' %(emp.name, emp.get_salary()))if __name__ == '__main__':main()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/37612.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/37612.shtml
英文地址,請注明出處:http://en.pswp.cn/web/37612.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

六西格瑪綠帶培訓的證書有什么用處?

近年來&#xff0c;六西格瑪作為一套嚴謹而系統的質量管理方法&#xff0c;被廣泛運用于各行各業。而六西格瑪綠帶培訓證書&#xff0c;作為這一方法論中基礎且重要的認證&#xff0c;對于個人和企業而言&#xff0c;都具有不可忽視的價值。本文將從多個角度深入探討六西格瑪綠…

重寫功能 rewrite

Nginx服務器利用 ngx_http_rewrite_module 模塊解析和處理rewrite請求&#xff0c;此功能依靠 PCRE(perl compatible regular expression)&#xff0c;因此編譯之前要安裝PCRE庫&#xff0c;rewrite是nginx服務器的重要功能之 一&#xff0c;用于實現URL的重寫&#xff0c;URL的…

充電寶口碑哪個好?好用充電寶品牌有哪些?好用充電寶推薦

充電寶作為我們日常生活和出行的重要伙伴&#xff0c;其品質和性能直接影響著我們的使用體驗。今天&#xff0c;就來和大家探討一下充電寶口碑哪個好&#xff0c;為大家盤點那些備受贊譽的好用充電寶品牌&#xff0c;并向您推薦幾款值得入手的充電寶&#xff0c;外出時不再擔心…

mac英語學習工具:Eudic歐路詞典 for Mac 激活版

Eudic歐路詞典是一款非常受歡迎的英語學習軟件&#xff0c;它提供了豐富的詞匯解釋、例句、同義詞、反義詞等功能&#xff0c;幫助用戶更好地理解和掌握英語單詞。 以下是Eudic歐路詞典的一些主要特點&#xff1a; 海量詞匯庫&#xff1a;Eudic歐路詞典擁有龐大的詞匯庫&#…

flutter photo_manager 報錯:Error: ‘DecoderCallback‘ isn‘t a type.

看看是不是你的photo_manager版本少于3.0。如果是少于3.0&#xff0c;請及時升級到3.0及以上版本&#xff0c;同時因為photo_manager3.0不再提供 AssetEntityImageProvider 這個方法&#xff0c;會導致報錯&#xff0c;不要慌&#xff0c;請添加下方的庫即可解決問題&#xf…

為什么人人都要懂一些銷售思維

創業看事情的高度、考慮的維度比做銷售更高、更復雜、更全面&#xff0c;銷售思維、銷售方法更多時候用在解決局部問題&#xff0c;幫我們打局部戰爭&#xff0c;它是術。 但是&#xff0c;我仍然認為&#xff0c;銷售思維是一種很有用、有效、有力量、必要的思維。我們每個人…

面試題002-Java-Java集合

面試題002-Java-Java集合 目錄 面試題002-Java-Java集合題目自測題目答案1. 說說 List,Set,Map 三者的區別&#xff1f;三者底層的數據結構&#xff1f;2. 有哪些集合是線程不安全的&#xff1f;怎么解決呢&#xff1f;3. 比較 HashSet 、LinkedHashSet 和 TreeSet 三者的異同&…

簡過網:考一建需要報培訓班嗎?報班費用是多少錢

近幾年來&#xff0c;越來越多的朋友都開始關注和參與備考一建&#xff0c;那么&#xff0c;大家在備考一建時&#xff0c;都報培訓班了嗎&#xff1f;報班的費用是多少錢&#xff1f;接下來&#xff0c;我們一塊來了解一下吧&#xff1f; ? 一、考一建需要報培訓班嗎&#…

【Jetpack】Lifecycle之自定義LifecycleOwner

Lifecycle設計講解 Lifecycle的設計其實十分簡單&#xff0c;主要就是Lifecycle對象和LifecycleOwner接口 Lifecycle用于記錄對象的生命周期&#xff0c;以及在生命周期發生改變時通知外部 LifecycleOwner用于表示對象具備生命周期管理能力 LifecycleOwner的實現方式很簡單&…

賽目科技三度遞表:凈利率及資產回報率不斷下滑,經營成本越來越高

《港灣商業觀察》施子夫 5月29日&#xff0c;北京賽目科技股份有限公司&#xff08;以下簡稱&#xff0c;賽目科技&#xff09;第三次遞表港交所&#xff0c;公司擬主板上市&#xff0c;獨家保薦機構為光銀國際。 公開信息顯示&#xff0c;賽目科技此前曾于2022年12月&#x…

Java全套智慧校園系統源碼:核心功能、發展趨勢、基于電子班牌: Android 7.1+小程序:原生開發+多學校Saas 模式

Java全套智慧校園系統源碼&#xff1a;核心功能、發展趨勢、基于電子班牌&#xff1a; Android 7.1小程序&#xff1a;原生開發多學校Saas 模式 智慧校園系統是一個集成了多種功能的綜合性平臺&#xff0c;旨在提升校園內的教學、管理、服務等方面的效率和體驗。那么&#xff…

比較(五)利用python繪制棒棒糖圖

比較&#xff08;五&#xff09;利用python繪制棒棒糖圖 棒棒糖圖&#xff08;Lollipop plot&#xff09;簡介 棒棒糖圖實際上是修飾后的條形圖。當在處理大量的值&#xff0c;并且當這些值都很高時&#xff0c;棒棒糖圖就很有用。 快速繪制 基于matplotlib import pandas as…

【前端環境1】安裝nvm

【前端環境1】安裝nvm 寫在最前面一、下載nvm二、安裝教程三、驗證nvm安裝 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻時光&#xff0c;感謝你的陪伴與支持 ~ &#x1f680; 歡迎一起踏上探險之旅&#xff0c;挖掘無限可能&#xff0c;共同成…

狗都能看懂的Reinforcement Learning簡介

文章目錄 一、什么是強化學習二、強化學習的應用 一、什么是強化學習 強化學習的流程可以用上面這張圖來說明&#xff1a;智能體&#xff08;Agent&#xff09;對環境進行觀測&#xff0c;然后根據觀測結果&#xff08;Observation / State&#xff09;采取相應的動作&#xff…

實現Ubuntu計劃任務的反彈shell

一、實驗環境 Ubuntu&#xff1a;IP地址&#xff1a;192.168.223.156 Kali : IP地址&#xff1a;192.168.223.152 二、編寫crontab計劃任務 在Ubuntu的系統中使用crontab -e命令編寫計劃任務&#xff0c;如下所示&#xff1a; 作用&#xff1a;是將一個交互式的bash …

device_node和platform_device的生成流程

1. machine_desc的匹配 《這篇》有介紹DT_MACHINE_START的一些初始化操作&#xff0c;匹配上就會在后續的初始化中調用DT_MACHINE_START的成員來初始化系統的設備樹&#xff0c;時鐘&#xff0c;中斷等 start_kernelsetup_arch(&command_line);mdesc setup_machine_fdt(…

行列視報表系統制作的報表與廠級監控信息系統(SIS)系統中的報表有什么區別?

廠級監控信息系統是集過程實時監測、優化控制及生產過程管理為一體的廠級自動化信息系統&#xff0c;是處于DCS以及相關輔助程控系統與全廠管理信息系統之間的一套實時廠級監控信息系統&#xff0c;該產品也是本公司的一套獨立產品。 SIS系統中的報表只是其中的一個模塊&#…

混合云管道的未來:集成 MinIO、Tailscale 和 GitHub Actions

數據處理是現代軟件開發的基本實踐。它使團隊能夠自動收集、處理和存儲數據&#xff0c;確保高質量的數據和高效的處理。 在本文中&#xff0c;我們將探討如何建立一個全面的數據處理管道&#xff0c;重點介紹如何使用 Tailscale GitHub Action 進行安全網絡。此設置還將包含 …

植物大戰僵尸雜交版手機下載與安裝全攻略

植物大戰僵尸雜交版是一款深受玩家喜愛的策略冒險游戲&#xff0c;以其豐富的植物種類、多樣的關卡設計和趣味的玩法著稱。本文將為您提供詳細的下載與安裝教程&#xff0c;幫助您快速上手&#xff0c;享受游戲帶來的樂趣。 游戲簡介 植物大戰僵尸雜交版在傳統玩法的基礎上&a…

【機器學習】語音轉文字 - FunASR 的應用與實踐(speech to text)

本文將介紹 FunASR&#xff0c;一個多功能語音識別模型&#xff0c;包括其特點、使用方法以及在實際應用中的表現。我們將通過一個簡單的示例來展示如何使用 FunASR 將語音轉換為文字&#xff0c;并探討其在語音識別領域的應用前景。 一、引言 隨著人工智能技術的不斷發展&am…