Python--面向對象進階

来源:https://www.cnblogs.com/yanjieli/archive/2018/11/27/10016075.html
-Advertisement-
Play Games

isinstance和issubclass isinstance isinstance(obj1,obj2):判斷對象與類之間的關係,判斷第一個參數是否是第二個參數的實例。 type()函數和isinstance()函數兩者有什麼區別呢? issubclass issubclass(obj1,obj ...


isinstance和issubclass

isinstance

isinstance(obj1,obj2):判斷對象與類之間的關係,判斷第一個參數是否是第二個參數的實例。

>>> n1 = 10
>>> isinstance(n1, int) #判斷n1是否是數字類型,如果是返回True如果不是防護False
True

>>> class A(object):
...     pass
...
>>> a1 = A()
>>> isinstance(a1, A)  # 判斷a1是否是類A的對象,如果是返回True,如果不是返回False
True

type()函數和isinstance()函數兩者有什麼區別呢?

>>> print(type(1) is int)
True
>>> print(isinstance(1, int))
True

#從上面的結果看,兩者的結果都是True,那麼type()與isinstance()的區別在哪呢?
#從接下來的例子,就能夠清晰看出來。

class A:pass
class B(A):pass

b = B()

print(isinstance(b, A)) # True
print(isinstance(b, B)) # True

print(type(b))  # <class '__main__.B'>
print(type(b) is B) # True
print(type(b) is A) # False

#總結:
    isinstance()是可以用在繼承的關係上;而type()不能用來檢測繼承關係。

issubclass

issubclass(obj1,obj2):用來描述一個類與另一個類之間的關係,判斷一個類是否是另一個類的子類

class A:pass
class B(A):pass

print(issubclass(B, A)) # True
print(issubclass(A, B)) # False

# 總結:
    類B是類A的子類,類A不是類B的子類

反射

什麼是反射?

反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,併在Lisp和麵向對象方面取得了成績。

Python中的反射:通過字元串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)

四個可以實現自省的函數:hasattr getattr setattr delattr

下列方法適用於類和對象(一切皆對象,類本身也是一個對象)

getattr()

def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass
getattr

具體使用:

  (1)getattr(obj,屬性名)----> 傳入字元串類型的屬性名,返回屬性的值,相當於執行了“obj.屬性名”

  (2)getattr(obj,方法名)----> 傳入字元串類型的方法名,返回對應方法的記憶體地址。

  謹記:如果第二個參數不存在的話,就會報錯。

class A:
    name = "小白"
    age = 18

    def func(self):
        print("in the func")

print(A.name)
print(A.age)

# 使用反射的形式,操作類的屬性
print(getattr(A, 'name'))

# 使用反射操作類中的方法
a = A()
ret = getattr(a, 'func')    # 得到了func方法的記憶體地址
ret()       # 調用func()方法

hasattr()

def hasattr(*args, **kwargs): # real signature unknown
    """
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
    """
    pass
hasattr

具體使用: 

  hasattr(obj,字元串類型的屬性名/方法名)--->判斷對象中是否擁有指定屬性/方法,返回True/False。

  謹記:所以hasattr經常和getattr一起使用,先用hasattr判斷,再使用getattr取值。

# 例子1:通過hasattr判斷,再用getattr來取值。
class A:
    name = "xiao"
    age = 18

inpu = input('>>>: ')
if hasattr(A, inpu):
    print(getattr(A, inpu))
else:
    print("A類中沒有對應的屬性")

>>>: name
xiao
>>>: sex
A類中沒有對應的屬性

# 例子2:
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        for key in self.__dict__:           #__dict__查看對象的所有屬性
            print(key, self.__dict__[key])  # key self.__dict__[key]

stu1 = Student("小白", 18)
if hasattr(stu1, 'show'):
    func = getattr(stu1, 'show')     # 返回方法的記憶體地址,賦值給func()
    func()

name 小白
age 18

setattr()

def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass
setattr

具體使用:

  setattr(obj,'name',value) ---->通過反射的方式為一個對象設置屬性(增改操作),相當於obj.name=value

# 正常情況下,想給對象設置一個值。
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        for key in self.__dict__:
            print(key, self.__dict__[key])

stu1 = Student("小白", 18)
stu1.name = "小黃"
print(stu1.name)    # 小黃


# 除了上面的方式之外,還有一種方式為對象設置屬性,通過反射的形式.
setattr(stu1, 'name', '菜農')
print(stu1.__dict__)    # {'name': '菜農', 'age': 18}
print(stu1.name)    # 菜農

除了給對象綁定屬性,還可以對象綁定一個函數。

# 創建一個函數,通過setattr給對象綁上這個函數
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        for key in self.__dict__:
            print(key, self.__dict__[key])

stu1 = Student("小白", 18)

def func():
    print('In func')

setattr(stu1, 'func1', func)
stu1.func1()        # In func
print(stu1.__dict__)    # {'name': '小白', 'age': 18, 'func1': <function func at 0x00000226123740D0>}

delattr()

def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.
    
    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
delattr

具體使用:

  delattr(obj,'name'):通過反射的方式,刪除對象中的屬性(刪除操作)

class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        for key in self.__dict__:
            print(key, self.__dict__[key])


stu1 = Student("小白", 18)
# 正常方法
del stu1.name
print(stu1.__dict__)    # {'age': 18}

# 通過delattr反射的方式
delattr(stu1, 'name')
print(stu1.__dict__)    # {'age': 18}

類使用反射

類:靜態屬性 類方法 靜態方法

class Student(object):
    name = "小白"

    @classmethod
    def check_course(cls):
        print("查看課程")

    @staticmethod
    def login():
        print("登錄")

# 檢查是否含有某屬性
print(hasattr(Student, "login"))    # 檢測Student類中是否有login方法,如果有返回True,沒有返回False

# 通過反射查看靜態屬性
print(getattr(Student, 'name'))

# 通過反射調用方法
print(getattr(Student, "check_course"))  # 得到的是類方法的記憶體地址
getattr(Student, "check_course")()  # 調用類方法
print(getattr(Student, "login"))    # 得到的是靜態方法的記憶體地址
getattr(Student, "login")() # 調用靜態方法

# 一般情況hasattr和getattr聯用, 示例:
num = input('>>>')  # 等待用戶輸入
if hasattr(Student, num):   # 判斷用戶輸入的方法是否有,如果有才執行。
    getattr(Student, num)()

對象使用反射

class A(object):
    def __init__(self, name):
        self.name = name

    def func(self):
        print(" In func ")


a = A("小白")
print(a.name)
print(getattr(a, "name"))
getattr(a, "func")()

模塊使用反射

import os
os.rename('__init__.py', 'init')
getattr(os, 'rename')('init', '__init__.py')    # os.rename('init', '__init__.py')

自定義模塊使用反射

既然反射能夠操作模塊,那麼當前文件其實也是一個模塊,通過sys.modules可以看出,當前文件就是sys.modules['__main__']。

import sys
def wahaha():
    print("wahaha")

def qqxing():
    print("qqxing")

wahaha()
qqxing()

my_file = sys.modules['__main__']
getattr(my_file,
'wahaha')() getattr(my_file, 'qqxing')()

通過sys.modules['__main__']好像完成了要求,但是,仔細想一下,使用__main__表示當前文件,假如在另外一個py文件中把當前文件導入,此時__main__便指向的是另外一個py文件,使用sys.modules['__main__']這種方式顯然是不妥的,那麼要怎麼解決?

使用sys.modules[__name__]就能完美解決,因為__name__就是'__main__'。

#通過sys.modules[__name__]反射當前模塊<br>import sys
import sys
def func():
    print("本模塊函數func")

getattr(sys.modules[__name__], 'func')()    # 本模塊函數func

  總結:

  sys.modules['__main__'] : __main__會隨著文件的不同而不同,存在安全隱患。

  sys.modules[__name__]:__name__不管在哪裡導入這個模塊,都代表這個文件。

反射總結

  (1)hasattr():判斷一個對象中是否能夠調用一個名字,返回True/False

  (2)getattr():返回一個對象中的名字的值

  (3)setattr():為一個對象設置屬性(增加/修改操作)

  (4)delattr():刪除一個對象的某個屬性(刪除操作)

# 反射
# hasattr, getattr
# 類名.名字
    # getattr(類名, '名字')
# 對象名.名字
    # getattr(對象, '名字')
# 模塊名.名字
    # import 模塊
    # getattr(模塊, '名字')
# 自己文件.名字
    # import sys
    # getattr(sys.modules[__main__], '名字')

反射的應用

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# __author__ = "yanjieli"
# Date: 2018/11/25/025

import sys


class Int(object):
    def __init__(self, name):
        self.name = name


class Manager(Int):
    OPERATE_LIST = [
        ('創建課程', 'create_course'),
        ('招聘老師', 'create_Teacher'),
        ('查看課程', 'check_course'),
        ('查看學生信息', 'check_userinfo'),
    ]

    def create_course(self):
        print("創建課程")

    def create_Teacher(self):
        print("招聘老師")

    def check_course(self):
        print("查看課程")

    def check_userinfo(self):
        print("查看學生信息")


class Teacher(Int):
    OPERATE_LIST = [
        ('查看課程', 'check_course'),
        ('查看學生成績', 'check_achievement'),
    ]

    def check_course(self):
        print("查看課程")

    def check_achievement(self):
        print("查看學生成績")


class Student(Int):
    OPERATE_LIST = [
        ('查看課程', 'check_course'),
        ('選擇課程', 'choose_course'),
        ('查看已選課程', 'choosed_course'),
        ('jsdklfjskld', 'aa'),
    ]

    def check_course(self):
        print("查看課程")

    def choose_course(self):
        print("選擇課程")

    def choosed_course(self):
        print("查看已選課程")


def login():
    username = input('user:>>>')
    password = input('password:>>>')
    with open("user_info", encoding="utf-8") as f:
        for line in f:
            user, pwd, ident = line.strip().split("|")
            if username == user and password == pwd:
                print("歡迎您!%s" % user)
                return user, ident
        else:
            print("登錄失敗")
            exit()


def main():
    user, id = login()
    cls = getattr(sys.modules['__main__'], id)  # 通過反射拿到當前登錄用戶所屬的類,如果是學生,則拿到學生類;
    operate_list = cls.OPERATE_LIST
    obj = cls(user)
    for index, i in enumerate(operate_list, 1):
        print(index, i[0])      # 列印出所有的功能
    option = int(input("option: >>>"))
    option_itme = operate_list[option -1]   # 拿到的是一個元組,比如:('創建課程', 'create_course'),
    getattr(obj, option_itme[1])()     # 通過反射拿到所輸入的選項對應的方法並執行


main()
反射應用示例

內置方法

內置方法:內置方法就是不需要程式員定義,本身就存在類中的方法。內置方法又稱為雙下方法,魔術方法。

內置方法通常長成這樣:__名字__。 每一個雙下方法都有它自己的特殊意義

所有的雙下方法,都不需要我們直接調用,都有另外一種自動觸發它的方法。而是總有一些其他的 內置方法 特殊的語法 來自動觸發這些 雙下方法

__call__

__call__ 方法的執行是由對象後加括弧觸發的,即:對象()。擁有此方法的對象可以像函數一樣被調用。

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __call__(self, *args, **kwargs):
        print('調用對象的__call__方法')


a = Person('張三', 24)  # 類Person可調用
a()  # 對象a可以調用
class A(object):
    def __call__(self, *args, **kwargs):
        print("執行了call方法")


class B(object):
    def __init__(self, cls):
        print("在實例化A之前做一些事情")
        self.obj = cls()
        self.obj()
        print("在實例化A之後做一些事情")


a = A()
a()     # 對象() == 相當於調用__call__方法

A()()   # 類名()() 相當於先實例化得到了一個對象,再對對象(), ==> 和上面的結果一樣,相當於調用__call__方法
B(A)

__len__

計算對象的長度,如果類中定義了__len__方法,那麼在對象中就能用內置函數len(obj),就會自動調用__len__方法。

class Foo(object):
    def __init__(self, s):
        self.s = s

    def __len__(self):
        print('調用了__len__方法, 計算長度')
        return len(self.s)


a = Foo("aaaa")
print(len(a))   # 自動調用了__len__方法
'''
列印結果:
調用了__len__方法, 計算長度
4
'''

__new__

網上經常有一個笑話“程式員可以自己new一個對象”, 到底new有什麼作用呢?

__new__又稱為構造方法,通過__init__()方法,我們知道初始化一個實例需要經歷的幾個步驟中的第一步就是在記憶體空間中開闢一個對象空間,這個對象空間是__init__方法開闢的麽?其實不是,在init之前,實例化對象的第一步是通過__new__方法創建一個對象空間。

class Fuu():
    def __new__(cls, *args, **kwargs):  # 構造方法,構造了對象的空間
        print("執行了__new__方法")
        return object.__new__(cls)  # 或者super().__new(cls) # 調用了object類中的__new__方法

    def __init__(self, name, age):  # 初始化方法
        print("執行了init方法")
        self.name = name
        self.age = age


c1 = Fuu("小白", 18)
"""
就這樣執行可以列印出:
執行了__new__方法
執行了init方法
"""

從上面的例子,我們可以更加清晰的得到初始化一個對象所經歷的過程:

  1、實例化Fuu類,應該先執行其__new__方法。

  2、但是Fuu類中沒有定義__new__方法,所以到object父類中執行object的__new__方法。

    回顧調用父類的兩種方法:

      object.__new__(cls)

      super().__new__(cls)

  3、此時在記憶體中開闢一塊對象空間。

  4、才執行init初始化方法,把地址傳給self,給對象封裝屬性。

總結:構造方法__new__和初始化方法__init__之間的區別?

形象的說,類好比一個人類型的模板,__new__構造方法就是捏小人的過程(捏出來的每一個小人都是一樣的),__init__初始化方法好比給小人穿衣服的過程(為對象封裝屬性),一定是先有__new__方法,後有__init__。

單例模式:一個類只有一個實例的時候,這種就叫做單例模式。

# 單例模式:一個類只有一個實例。
# 思考:如果使得一個類只能實例化一次,也就是這要控制只能開闢一次空間,就能實現單例模式。


class Singleinstance():
    __INSTANCE = None   # 通過設置一個標誌位,用來使得只能運行一次new方法

    def __new__(cls, *args, **kwargs):
        if not cls.__INSTANCE:
            cls.__INSTANCE = object.__new__(cls)
        return cls.__INSTANCE

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

obj1 = Singleinstance('小白', 18)
obj2 = Singleinstance('小黑', 20)

print(obj1.name, obj1.age)
print(obj2.name, obj2.age)
print(obj1)
print(obj2)

>>>
小黑 20
小黑 20
<__main__.Singleinstance object at 0x000001C1657F6048>
<__main__.Singleinstance object at 0x000001C1657F6048>

'''
總結:由上列印可以看到不論實例化多少對象,都是一個對象,都會已最後一個為準。
'''

__str__ 與 __repr__

__str__

如果想把一個類的實例變成str類型,列印對象名的時候就執行__str__方法。

__str__ : str(obj),要求必須實現了__str__,要求這個方法的返回值必須是字元串str類型

三種場景會觸發__str__方法:

  • (1)當你列印一個對象名的時候,就會就會觸發__str__。  
  • (2)當你使用%s格式化輸出對象的時候,也會觸發__str__。
  • (3)強制轉換數據類型的時候,也會觸發__str__。
class Student:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __str__(self):
        return "%s %s %s" % (self.name, self.age, self.sex)

st1 = Student("小白", 18, "")
print(st1)                  #1.列印對象名,自動觸發__str__方法
>>>
小白 18 男


student_list = []
student_list.append(st1)
for index, i in enumerate(student_list):
    print('%s %s'% (index, i))          #2.當使用%s格式化的時候,自動觸發__str__

>>>
0 小白 18 男

__repr__

1、__repr__是__str__方法的備胎,如果有__str__就使用__str__,否則執行__repr__。

# (1)同時存在__str__和__repr__兩個方法:
class Student:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    def __str__(self):
        return "str: %s %s %s" % (self.name, self.age, self.sex)

    def __repr__(self):
        return "repr: %s %s %s" % (self.name, self.age, self.sex)


st1 = Student("小白", 18, "")
print(st1)
>>>
str: 小白 18# (2)只存在__repr__方法時,再次列印對象名:
class Student:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    # 註釋掉__str__雙下方法
    # def __str__(self):
    #     return "str: %s %s %s" % (self.name, self.age, self.sex)

    def __repr__(self):
        return "repr: %s %s %s" % (self.name, self.age, self.sex)


st1 = Student("小白", 18, "")
print(st1)         # 當__str__沒有時,執行__repr__方法
>>>
repr: 小白 18 男

如果__repr__僅僅只是__str__的備胎,那麼它就沒有存在的意義了。所有__repr__還是有它自己的用武之地的時候:

2、如果使用內置函數repr(obj),或者通過%r格式化的時候,就會自動觸發__repr__方法,不管有沒有__str__,都調用__repr__。

st1 = Student("小白", 18, "")
print(repr(st1))
>>>
repr: 小白 18 男

小技巧:

python中之所有既有__str__,又有__repr__,__str__用於顯示給用戶看,__repr__用於顯示給開發人員看。 下麵就有一個偷懶的小辦法:

__str__=__repr__

擴展知識:

class Fcc:
    def __str__(self):
        return "Fcc.str"

    def __repr__(self):
        return "Fcc.repr"


class Ecc(Fcc):
    def __str__(self):
        return "Ecc.str"

    def __repr__(self):
        return "Ecc.repr"


E1 = Ecc()
print(E1)
>>>
Ecc.str
'''
(1) 先去子類中查找,先調用__str__方法。
(2) 如果把子類的__str__方法註釋掉,會去父類中查找父類的__str__方法
(3) 如果把父類的__Str__的方法註釋掉,會再回到子類中執行備胎__repr__方法。
'''

__del__

__del__ 析構方法:在刪除某個類的對象的時候,就會觸發這個雙下方法,再刪除這個對象。即“del obj”執行這個刪除對象的代碼的時候,觸發__del__析構方法。

運用的場景:文件資源,網路資源等。

class	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 例子: 頁面效果: 具體方法: 執行後的頁面效果: createDocumentFragment()方法,則是用了創建一個虛擬的節點對象,或者說,是用來創建文檔碎片節點。它可以包含各種類型的節點,在創建之初是空的。DocumentFragment節點不屬於文檔樹,繼承的parentNode屬性總是n ...
  • echarts 真的是個神奇的東西,最近做了一個需要點亮中國的移動端項目,前期就怎樣點亮中國做了調研,發現微博當初炫酷的點亮效果就是用echarts做的,於是研究了一下。 一連研究了一堆demo,不管從官網還是GitHub上面,大多demo的數據都是自己的格式,於是乎根據API自己研究了一下,把de ...
  • 前後端分離的開發模式已經是目前前端的主流模式,至於為什麼會前後端分離的開發我們就不做過多的闡述,既然是前後端分離的模式開發肯定是離不開前端的數據模擬階段。 我們在開發的過程中,由於後臺介面的沒有完成或者沒有穩定之前我們都是採用模擬數據的方式去進行開發項目,這樣會使我們的前後端會同時的進行,提高我們的 ...
  • 一、HTTP JSON方式的缺點 1. JSON序列化效率低 2. 多語言服務治理功能低 二、關於RPC框架 RPC 框架大致分為兩類,一種是偏重服務治理,另一種側重跨語言調用 2.1 服務治理型 特點 功能豐富,提供高性能的遠程調用、服務發現及服務治理能力,適用於大型服務的服務解耦及服務治理,對於 ...
  • 簡單工廠模式,需要說明的是,它並不屬於GOF 23種設計模式中的一種。但它卻豐富了工廠模式家族,因為其簡單的思想和使用方式,也有很廣泛的使用 簡單工廠模式又稱為靜態工廠模式,它用來確定創建哪一種對象的實例。這種模式應該說是最簡單最實用的工廠模式了,它將外界創建對象的邏輯收集起來,做到了對外界隔離對象 ...
  • 一. 簡述編程過程中, 註釋的作用? (1) 方便開發人員自己理清楚代碼思路 因為開發人員在拿到一個需求時, 首先應該思考的是如何將需求問題, 分解成具體的實施步驟; 第一步幹啥, 第二步幹啥, 第三步幹啥, 安排的明明白白; 這一步也是零基礎學員欠缺的步驟, 而且是非常重要的步驟(這都理不清, 代 ...
  • 頭文件: 建立一個棧 //例如 加入一個新的元素 詢問棧頂元素 彈出棧頂元素 棧裡面有多少個元素`s.size()` ...
  • 在房間里,有衣櫃(列表,裡面的東西一個一個的)一對男女(集合:不能出現相同的)廚具(元組:一個一個的,但是不能改動)佐料盒(字典:一個標簽裝一種料) 上面的是建立空間,把內容放進去,下麵的這些,有就是有沒有就是沒有, 雜貨間(字元串:什麼都有)窗戶(布爾:有窗或沒窗)桌椅(整數:每一個都是獨立的... ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...