Python(六)面向對象

来源:http://www.cnblogs.com/suoning/archive/2016/06/07/5551173.html
-Advertisement-
Play Games

本章內容: 創建類和對象 面向對象三大特性(封裝、繼承、多態) 類的成員(欄位、方法、屬性) 類成員的修飾符(公有、私有) 類的特殊成員 面向對象編程是一種編程方式,此編程方式的落地需要使用 “類” 和 “對象” 來實現,所以,面向對象編程其實就是對 “類” 和 “對象” 的使用。 類就是一個模板, ...


本章內容:

  • 創建類和對象
  • 面向對象三大特性(封裝、繼承、多態)
  • 類的成員(欄位、方法、屬性)
  • 類成員的修飾符(公有、私有)
  • 類的特殊成員
創建類和對象

面向對象編程是一種編程方式,此編程方式的落地需要使用 “類” 和 “對象” 來實現,所以,面向對象編程其實就是對 “類” 和 “對象” 的使用。

  類就是一個模板,模板里可以包含多個函數,函數里實現一些功能

  對象則是根據模板創建的實例,通過實例對象可以執行類中的函數

  • class是關鍵字,表示類
  • 創建對象,類名稱後加括弧即可
# 創建類
class Foo:
     
    def buy(self):
        print("This is buy.")
 
    def Hello(self, name):
        print("This is hello.")
 
# 根據類Foo創建對象obj
obj = Foo()
obj.buy()            #執行Bar方法
obj.Hello('nick')    #執行Hello方法

類和對象在記憶體中是如何保存的?

類以及類中的方法在記憶體中只有一份,而根據類創建的每一個對象都在記憶體中需要存一份,大致如下圖:

 

如上圖所示,根據類創建對象時,對象中除了封裝 name 和 age 的值之外,還會保存一個類對象指針,該值指向當前對象的類。

當通過 obj1 執行方法時,過程如下:

  1. 根據當前對象中的 類對象指針 找到類中的方法
  2. 將對象 obj1 當作參數傳給 方法的第一個參數 self 

註:Java和C#來說只支持面向對象編程,而python比較靈活即支持面向對象編程也支持函數式編程

面向對象三大特性

面向對象的三大特性是指:封裝、繼承和多態。

一、封裝

封裝,顧名思義就是將內容封裝到某個地方,以後再去調用被封裝在某處的內容。

所以,在使用面向對象的封裝特性時,需要:

  • 將內容封裝到某處
  • 從某處調用被封裝的內容

1、將內容封裝到某處

self 是一個形式參數,當執行 obj = Foo('nick', 18 ) 時,self 等於 obj

                     當執行 obj2 = Foo('jenny', 21 ) 時,self 等於 obj2

2、從某處調用被封裝的內容

調用被封裝的內容時,有兩種情況:

  • 通過對象直接調用
  • 通過self間接調用
class Foo:
 
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
obj = Foo('nick', 18)
print obj.name    # 直接調用obj對象的name屬性
print obj.age     # 直接調用obj對象的age屬性
 
obj2 = Foo('jenny', 21)
print obj2.name    # 直接調用obj2對象的name屬性
print obj2.age     # 直接調用obj2對象的age屬性
class Foo:
  
    def __init__(self, name, age):
        self.name = name
        self.age = age
  
    def detail(self):
        print self.name
        print self.age
  
obj = Foo('nick', 18)
obj.detail()  # Python預設會將obj傳給self參數,即:obj.detail(obj),所以,此時方法內部的 self = obj,即:self.name 是 nick ;self.age 是 18
  
obj2 = Foo('jenny', 21)
obj2.detail()  # Python預設會將obj2傳給self參數,即:obj1.detail(obj2),所以,此時方法內部的 self = obj2,即:self.name 是 jenny ; self.age 是 21
#封裝
#非主流方式
class Foo:

    def fetch(self):
        print(self.nick)

    def add(self):
        print(self.jenny)

obj = Foo()
obj.nick = "Nick_cool"
obj.fetch()

# obj2 = Foo()
obj.nick = "Nick_cool_2"
obj.fetch()

obj1 = Foo()
obj1.jenny = "Jenny_nice"
obj1.add()


#封裝

class Foo:

    def __init__(self,bk):
        """ 構造方法 """          #析構方法在垃圾回收是解釋器自己調用
        self.name = bk
        self.job = "pythoner"   # obj.job = "pythoner"
        self.age = 18           # obj.age = 18

    def fetch(self):
        print(self.name)
        print(self.age)
        print(self.job)

obj = Foo("nick")
obj.fetch()

綜上所述,對於面向對象的封裝來說,其實就是使用構造方法將內容封裝到 對象 中,然後通過對象直接或者self間接獲取被封裝的內容。

二、繼承 

對於面向對象的繼承來說,其實就是將多個類共有的方法提取到父類中,子類僅需繼承父類而不必一一實現每個方法。

註:除了子類和父類的稱謂,你可能看到過 派生類 和 基類 ,他們與子類和父類只是叫法不同而已。

# 繼承

# 基類
class Animals:

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

    def eat(self):
        print(self.name,"吃")


# 派生類
class dog(Animals):

    def tell(self):
        print("汪星人")

dog = dog("啊黃")
dog.tell()
dog.eat()

 

繼承 __init__

派生類預設不繼承基類__init__,需要用super聲明

class A:
    def __init__(self):
        self.name = "nick"

class B(A):
    def __init__(self):
        self.age = 18
        super(B, self).__init__()   #super首先找到B的父類A,然後把類B的對象self轉換為類A的對象,然後“被轉換”的類A對象調用自己的__init__函數
        # A.__init__(self)          #指定運行A中__init__,不推薦

obj = B()
print(obj.__dict__)

 

多繼承:

Python的類可以繼承多個類,Java和C#中則只能繼承一個類

Python3的類繼承多個類的尋找方法的方式,Python 3中沒有經典類、新式類之分

# 多繼承

class A:
    def f1(self):
        print("A")

class B(A):
    def f(self):
        print("B")

class C(A):
    def f(self):
        print("C")

class D(B):
    def f(self):
        print("D")

class E(C):
    def f1(self):
        print("E")

class F(D,E):
    def f(self):
        print("F")

f1 = F()
f1.f1()

Python2的類如果繼承了多個類,那麼其尋找方法的方式有兩種,分別是:深度優先廣度優先

  • 當類是經典類時,多繼承情況下,會按照深度優先方式查找
  • 當類是新式類時,多繼承情況下,會按照廣度優先方式查找

經典類和新式類,從字面上可以看出一個老一個新,新的必然包含了跟多的功能,也是之後推薦的寫法,從寫法上區分的話,如果 當前類或者父類繼承了object類,那麼該類便是新式類,否則便是經典類。

 

class D:

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 執行bar方法時
# 首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麽有,則繼續去D類中找,如果D類中麽有,則繼續去C類中找,如果還是未找到,則報錯
# 所以,查找順序:A --> B --> D --> C
# 在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了
a.bar()
經典類多繼承
class D(object):

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 執行bar方法時
# 首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麽有,則繼續去C類中找,如果C類中麽有,則繼續去D類中找,如果還是未找到,則報錯
# 所以,查找順序:A --> B --> C --> D
# 在上述查找bar方法的過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了
a.bar()
新式類多繼承

經典類:首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麽有,則繼續去D類中找,如果D類中麽有,則繼續去C類中找,如果還是未找到,則報錯

新式類:首先去A類中查找,如果A類中沒有,則繼續去B類中找,如果B類中麽有,則繼續去C類中找,如果C類中麽有,則繼續去D類中找,如果還是未找到,則報錯

註意:在上述查找過程中,一旦找到,則尋找過程立即中斷,便不會再繼續找了

 

函數方法里調用函數方法執行順序

# 函數方法里調用函數方法執行順序

class D:

    def buy(self):
        self.f1()       #調用 f1()

    def f1(self):
        print("This is D f1.")

class C(D):

    def f1(self):
        print("This is C f1.")

class B:

    def f1(self):
        print("This is B f1.")

class A(B, C):
    pass

obj = A()
obj.buy()

 

三、多態

  多態性(polymorphisn)是允許你將父對象設置成為和一個或更多的他的子對象相等的技術,賦值之後,父對象就可以根據當前賦值給它的子對象的特性以不同的方式運作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。   那麼,多態的作用是什麼呢?我們知道,封裝可以隱藏實現細節,使得代碼模塊化;繼承可以擴展已存在的代碼模塊(類);它們的目的都是為了——代碼重用。而多態則是為了實現另一個目的——介面重用!多態的作用,就是為了類在繼承和派生的時候,保證使用“家譜”中任一類的實例的某一屬性時的正確調用。   Pyhon不支持多態並且也用不到多態,多態的概念是應用於Java和C#這一類強類型語言中,而Python崇尚“鴨子類型”。
class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'


# 由於在Java或C#中定義函數參數時,必須指定參數的類型
# 為了讓Func函數既可以執行S1對象的show方法,又可以執行S2對象的show方法,所以,定義了一個S1和S2類的父類
# 而實際傳入的參數是:S1對象和S2對象

def Func(F1 obj):
    """Func函數需要接收一個F1類型或者F1子類的類型"""
    
    print obj.show()
    
s1_obj = S1()
Func(s1_obj) # 在Func函數中傳入S1類的對象 s1_obj,執行 S1 的show方法,結果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函數中傳入Ss類的對象 ss_obj,執行 Ss 的show方法,結果:S2.show
Python偽代碼實現Java或C#的多態
class F1:
    pass


class S1(F1):

    def show(self):
        print 'S1.show'


class S2(F1):

    def show(self):
        print 'S2.show'

def Func(obj):
    print obj.show()

s1_obj = S1()
Func(s1_obj) 

s2_obj = S2()
Func(s2_obj) 
Python “鴨子類型”
class Animal:
    def __init__(self, name):    # Constructor of the class
        self.name = name
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")
 
class Cat(Animal):
    def talk(self):
        return 'Meow!'
 
class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'
 
animals = [Cat('Missy'),
           Dog('Lassie')]
 
for animal in animals:
    print animal.name + ': ' + animal.talk()
通過Python模擬的多態

 

類的方法

類的成員可以分為三大類:欄位、方法和屬性。

註:所有成員中,只有普通欄位的內容保存對象中,即:根據此類創建了多少對象,在記憶體中就有多少個普通欄位。而其他的成員,則都是保存在類中,即:無論對象的多少,在記憶體中只創建一份。

 

 一、欄位

欄位包括:普通欄位和靜態欄位,他們在定義和使用中有所區別,而最本質的區別是記憶體中保存的位置不同,

  • 普通欄位屬於對象
  • 靜態欄位屬於
class Foo:
     
    # 靜態欄位
    country = "China"

    def __init__(self, name):

        # 普通欄位
        self.name = name

# 直接訪問靜態欄位
Foo.country

# 直接訪問普通欄位
obj = Foo("山西")

由上述代碼可以看出【普通欄位需要通過對象來訪問】【靜態欄位通過類訪問】,在使用上可以看出普通欄位和靜態欄位的歸屬是不同的。 

  • 靜態欄位在記憶體中只保存一份
  • 普通欄位在每個對象中都要保存一份

應用場景: 通過類創建對象時,如果每個對象都具有相同的欄位,那麼就使用靜態欄位

 

二、方法

方法包括:普通方法、靜態方法和類方法,三種方法在記憶體中都歸屬於類,區別在於調用方式不同。

  • 普通方法:由對象調用;至少一個self參數;執行普通方法時,自動將調用該方法的對象賦值給self
  • 類方法:由調用; 至少一個cls參數;執行類方法時,自動將調用該方法的複製給cls
  • 靜態方法:由調用;無預設參數;
class Foo:


    #靜態方法
    @staticmethod
    def xo(arg1, arg2):     #無預設參數,可不傳參數,可傳任意參數
        print("xo")


    #類方法
    @classmethod
    def xxoo(cls):             #定義類方法,至少有一個cls參數
        print(cls)


    #普通方法,類中
    def show(self):           #定義普通方法,至少有一個self參數
        print("show")


# 調用靜態方法
Foo.xo(1,2)

# 調用類方法
Foo.xxoo()

# 調用普通方法
obj = Foo:
obj.show()

相同點:對於所有的方法而言,均屬於類(非對象)中,所以,在記憶體中也只保存一份。

不同點:方法調用者不同、調用方法時自動傳入的參數不同。

 

三、屬性

由屬性的定義和調用要註意一下幾點:

  • 定義時,在普通方法的基礎上添加 @property 裝飾器;
  • 定義時,屬性僅有一個self參數
  • 調用時,無需括弧
               方法:foo_obj.func()
               屬性:foo_obj.prop

註意:屬性存在意義是:訪問屬性時可以製造出和訪問欄位完全相同的假象

      屬性由方法變種而來,如果Python中沒有屬性,方法完全可以代替其功能。

class Foo:

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

    # 屬性,將方法偽造成一種欄位
    @property
    def end(self):
        return self.name

    # 修改end值
    @end.setter
    def end(self, new_name):
        self.name = new_name


obj = Foo("nick")

# 調用屬性,不需要加括弧
result2 = obj.end
print(result2)

# 調用修改end.setter屬性(自動將jenny傳入當參數new_name)
obj.end = "jenny"

result3 = obj.end
print(result3)

 

類成員的修飾符

每一個類的成員都有兩種形式:

  • 公有成員,在任何地方都能訪問
  • 私有成員,只有在類的內部才能方法

 私有成員和公有成員的定義不同:私有成員命名時,前兩個字元是下劃線。(特殊成員除外,例如:__init__、__call__、__dict__等)

class Foo:

    xo = "xo"         #公有欄位
    __ox = "ox"     #私有欄位

    def __init__(self):
        self.name = "nick"         #公有欄位
        self.__name2 = "nick"   #私有欄位

私有成員和公有成員的訪問限制不同

靜態欄位

  • 公有靜態欄位:類可以訪問;類內部可以訪問;派生類中可以訪問
  • 私有靜態欄位:僅類內部可以訪問;
class C:

    name = "公有靜態欄位"

    def func(self):
        print C.name

class D(C):

    def show(self):
        print C.name


C.name         # 類訪問

obj = C()
obj.func()     # 類內部可以訪問

obj_son = D()
obj_son.show() # 派生類中可以訪問
公有靜態欄位
class C:

    __name = "公有靜態欄位"

    def func(self):
        print C.__name

class D(C):

    def show(self):
        print C.__name


C.__name       # 類訪問            ==> 錯誤

obj = C()
obj.func()     # 類內部可以訪問     ==> 正確

obj_son = D()
obj_son.show() # 派生類中可以訪問   ==> 錯誤
私有靜態欄位

普通欄位

  • 公有普通欄位:對象可以訪問;類內部可以訪問;派生類中可以訪問;
  • 私有普通欄位:僅類內部可以訪問;
class C:
    
    def __init__(self):
        self.foo = "公有欄位"

    def func(self):
        print self.foo  # 類內部訪問

class D(C):
    
    def show(self):
        print self.foo # 派生類中訪問

obj = C()

obj.foo     # 通過對象訪問
obj.func()  # 類內部訪問

obj_son = D();
obj_son.show()  # 派生類中訪問
公有欄位
class C:
    
    def __init__(self):
        self.__foo = "私有欄位"

    def func(self):
        print self.foo  # 類內部訪問

class D(C):
    
    def show(self):
        print self.foo # 派生類中訪問

obj = C()

obj.__foo     # 通過對象訪問    ==> 錯誤
obj.func()  # 類內部訪問        ==> 正確

obj_son = D();
obj_son.show()  # 派生類中訪問  ==> 錯誤
私有欄位

方法、屬性的訪問於上述方式相似,即:私有成員只能在類內部使用

ps:如果想要強制訪問私有欄位,可以通過 【對象._類名__私有欄位明 】訪問(如:obj._C__foo),不建議強制訪問私有成員。

 

類的特殊成員

成員名前如果有兩個下劃線,則表示該成員是私有成員,私有成員只能由類內部調用。

1. __doc__

表示類的描述信息

class Foo:
    """ 描述類信息 """

    def func(self):
        pass

print Foo.__doc__
#輸出:類的描述信息
__doc__

2. __module__ 和  __class__

  __module__ 表示當前操作的對象在那個模塊

  __class__     表示當前操作的對象的類是什麼

#!/usr/bin/env python
# -*- coding:utf-8 -*-

class C:

    def __init__(self):
        self.name = 'nick'
lib/aa.py
from lib.aa import C

obj = C()
print obj.__module__  # 輸出 lib.aa,即:輸出模塊
print obj.__class__      # 輸出 lib.aa.C,即:輸出類
index.py

3. __init__

構造方法,通過類創建對象時,自動觸發執行。

class Foo:

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


obj = Foo('nick')     # 自動執行類中的 __init__ 方法
__init__

4. __del__

析構方法,當對象在記憶體中被釋放時,自動觸發執行。

註:此方法一般無須定義,因為Python是一門高級語言,程式員在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python解釋器來執行,所以,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。

class Foo:

    def __del__(self):
        pass
__del__

5. __call__

對象後面加括弧,觸發執行。

註:構造方法的執行是由創建對象觸發的,即:對象 = 類名() ;而對於 __call__ 方法的執行是由對象後加括弧觸發的,即:對象() 或者 類()()

# __call__
class Foo:

    def __init__(self):
        print("This is init")

    def __call__(self, *args, **kwargs):
        print("This is call")
        return "CC"

obj = Foo()    # 執行 __init__
obj()              # 執行 __call__

result = Foo()()   # 執行 __call__
print(result)
__call__

6. __dict__

類或對象中的所有成員

class Province:

    country = 'China'

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

    def func(self, *args, **kwargs):
        print 'func'

# 獲取類的成員,即:靜態欄位、方法、
print Province.__dict__
# 輸出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}

obj1 = Province('shangxi',10000)
print obj1.__dict__
# 獲取 對象obj1 的成員
# 輸出:{'count': 10000, 'name': 'shangxi'}

obj2 = Province('shangdong', 3888)
print obj2.__dict__
# 獲取 對象obj1 的成員
# 輸出:{'count': 3888, 'name': 'shangdong'}
__dict__

 7. __str__

如果一個類中定義了__str__方法,那麼在列印對象時,預設輸出該方法的返回值。

class Foo:

    def __str__(self):
        return 'nick'


obj = Foo()
print obj
# 輸出:nick
__str__

8、__getitem__、__setitem__、__delitem__

用於索引操作,如字典。以上分別表示獲取、設置、刪除數據

class Foo:

    def __getitem__(self, item):
        print(item)

    def __setitem__(self, key, value):
        print(key, value)

    def __delitem__(self, key):
        print(key)

obj = Foo()

obj["nick"]                     # 自動觸發執行 __getitem__
obj["nick"] = "jenny"     # 自動觸發執行 __setitem__
del obj["nick"]                # 自動觸發執行 __delitem__
__getitem____setitem____delitem__

9、__getslice__、__setslice__、__delslice__

該三個方法用於分片操作,如:列表

class Foo(object):
 
    def __getslice__(self, i, j):
        print '__getslice__',i,j
 
    def __setslice__(self, i, j, sequence):
        print '__setslice__',i,j
 
    def __delslice__(self, i, j):
        print '__delslice__',i,j
 
obj = Foo()
 
obj[-1:1]                   # 自動觸發執行 __getslice__
obj[0:1] = [11,22,33,44]    # 自動觸發執行 __setslice__
del obj[0:2]                # 自動觸發執行 __delslice__
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上次我們學習了面向對象,“類”的創建及公有屬性的定義 公有屬性定義的單詞是:public 公有屬性表示內部所定義的成員對程式所有的部分可見,這裡的成員包括:數據成員、成員函數以及類型 也就是說,無論是程式的什麼部分,都可以直接訪問、修改這些類的對象的成員 這就意味誰都可以修改類對象里關鍵的數據信息, ...
  • 基於上篇文章"基於Tomcat + JNDI + ActiveMQ實現JMS的點對點消息傳送"很容易就可以編寫一個發佈/訂閱消息傳送例子,相關環境準備與該篇文章基本類似,主要的區別如下。 在Tomcat中配置JNDI 配置連接工廠和話題 在Web工廠中編寫代碼 新建一個發佈者Servlet 新建一個 ...
  • 本文介紹了用 SimpleDateFormat、Joda-Time、Apache-DateUtils 三種方式解析ISO8601日期字元串的異同 ...
  • 最近在看js,看到closure(閉包)這一塊兒的時候就想到了 java的匿名內部類 兩者都有涉及到變數/參數的引用問題。 先說java的匿名內部類,他的定義我就不多做說明瞭,可以參考地址 http://docs.oracle.com/javase/tutorial/java/javaOO/anon ...
  • c++重載運算符 by ysmor 重新解釋運算符的含義,叫做運算符重載 c++程式設計P277 不多說了,給代碼 輸入9 100 2 運行結果 THE END... 歡迎大家跟帖,並繼續關註我 註意:本博客為原創作品,csdn上的那篇也是我發的 鏈接http://blog.csdn.net/yig ...
  • VC++代碼是最接近彙編指令的高級語言,為了更加準確和深刻理解VC++編碼中所涉及的很多技術概念和編譯器參數的含義,從彙編指令層面進行剖析和解讀,有助於開發者更加準確、直觀、深刻理解高級語言中很多概念和技術的真正含義,對程式優化和編碼都有非常實用的重要價值。由於內容很多,我會分解為很多篇章進行解讀實 ...
  • 起源 1950晶體管電腦年代,歐美電腦學家合力所組成的聯席大會共同開發 ALGOL(ALGOrithmic Language),也稱為A語言。 1963年,劍橋大學將ALGOL 60語言發展成為CPL(Combined Programming Language)語言。 1967年,英國劍橋大學的 ...
  • urllib 模塊是一個高級的 web 交流庫,其核心功能就是模仿web瀏覽器等客戶端,去請求相應的資源,並返回一個類文件對象。urllib 支持各種 web 協議,例如:HTTP、FTP、Gopher;同時也支持對本地文件進行訪問。但一般而言多用來進行爬蟲的編寫,而下麵的內容也是圍繞著如何使用 u ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...