主頁 > 後端開發 > Python作用域、閉包與裝飾器

Python作用域、閉包與裝飾器

2021-07-24 13:01:09 後端開發

一、命名空間

1.1、全域命名空間

命名空間為 namespace 的直譯,決議如下:

num = 5
name = "xiaohao"

以上,我們簡單地定義了兩個變數,便等同于創建了兩個名字與物件的對應關系,這種建立名字與物件映射關系的行為便是命名
字典就是一個名字與值對應的典型例子,這使得 python 中的命名空間通常用字典實作,

print(globals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002F3C774FFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\86177\\Documents\\1.py', '__cached__': None, 'num': 5, 'name': 'xiaohao'}

呼叫globals方法便可回傳 全域命名空間 ,列印結果可以看到全域命名空間是一個字典物件,同時包含了我們剛剛定義的兩個變數,
包含 全域命名空間 在內有以下三種命名空間:

  • 區域命名空間 Local namespace:函式中定義的命名,包括函式的引數,
  • 全域命名空間 Global namespace:當前模塊中的命名,與其他模塊中 import 進來的命名,
  • 內置命名空間 Built-in namespace:Python 語言內置的命名,比如函式名 print、type 等等關鍵字,
a = 1 # a 處在全域命名空間

def func():
    b = 2 # b 處在區域命名空間

print(__name__) # __name__ 處在內建命名空間

1.2、內建命名空間

所謂的內建命名空間便是包括了 python 自帶的一些變數與函式,比如 dict,list,type,print 等等,這些都是由 python 默認從 builtins 模塊匯入,
我們可以配合 dir 函式列印一下 __builtins__ 模塊的內容,便可以看到內建命名空間中的內容,

print(dir(__builtins__))
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'breakpoint', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']

1.3、區域命名空間

程式當前執行的代碼塊內的命名都屬于區域命名空間,
locals 函式可以看到當前區域命名空間中的內容,

a = 1

def func():
    b = 2
    print(locals())

func()
{'b': 2}

如果在最外層代碼中呼叫 locals ,此時它與 glocals 輸出的內容是等價的,因為當程式執行到最外層代碼時,區域命名空間等同于全域命名空間,

a = 1

def func():
    b = 2
    print(locals())

func()

print(locals())
print(globals())
{'b': 2}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002203218FFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\86177\\Documents\\1.py', '__cached__': None, 'a': 1, 'func': <function func at 0x0000022032625820>}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000002203218FFD0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'C:\\Users\\86177\\Documents\\1.py', '__cached__': None, 'a': 1, 'func': <function func at 0x0000022032625820>}

1.4、命名空間的作用

命名空間包含了從名稱到物件的映射,大部分的命名空間都是通過 Python 字典來實作的,

命名空間可以將我們各部分的命名獨立,避免了它們之間的沖突,你在命名一個變數時不再需要翻遍整個專案來防止命名沖突導致影響其他部分的代碼,

a = 1

def func():
    a = 2
    print('區域命名空間的a:', a)

func()
print('全域命名空間的a:', a)
區域命名空間的a: 2
全域命名空間的a: 1

以上的兩個 a 處于不同的命名空間,它們之間互不影響,在區域命名空間的命名不會影響到全域命名空間的命名,

二、作用域

2.1、定義

我們了解到命名空間是可以獨立存在的,并且它們以一定的層次來構建,這使得我們能以一定范圍參考我們的變數,

限定變數名字的可用性的區域就是這個名字的作用域,并且作用域會直接決定我們參考一個變數時查找區域的順序,

a = 1  # 全域作用域

def func():
    b = 2  # 閉合作用域

    def func_2():
        c = 3  # 區域作用域

print(__name__)  # __name__ 處于內建作用域

在這段代碼中 a, b, c, __name__ 分別處于 全域作用域閉合作用域區域作用域內建作用域

一個函式內如果還定義有函式,則當前函式為閉合作用域,否則為區域作用域

作用域有四種:

  • 區域作用域 Local:最內層的函式 (def 或 lambda),
  • 閉合作用域 Enclosing:如果 A 函式內定義了一個 B 函式,那么相對 B 函式內的變數 A 函式內的變數就處于閉合作用域,
  • 全域作用域 Global:最外部定義的變數
  • 內建作用域 Built-in:內建模塊內定義的函式與關鍵字

python 尋找一個變數的順序是:LEGB,也就是 區域→閉合→全域→內建,
在這里插入圖片描述

2.2、global 和 nonlocal關鍵字

如果我們想在函式中修改全域作用域中的值,就只會在區域作用域中生成一個新的命名,

這會就需要global 關鍵字,它使得我們可以修改全域作用域內的變數,

a = 1 # 全域作用域的 a

def func():
    global a # 引入了全域作用域的 a 變數
    print('修改前的 a:', a)
    a = 2
    print('修改后的 a:', a)

func()
print('最終的 a:', a)
修改前的 a: 1
修改后的 a: 2
最終的 a: 2

nonlocal 關鍵字同理,它允許我們修改閉合作用域內的變數,

a = 1  # 全域作用域的 a

def func():
    a = 2  # 閉合作用域的 a 變數

    def func_2():
        nonlocal a  # 引入了閉合作用域的 a 變數
        print('修改前的 a:', a)
        a = 3

    func_2()
    print('閉合作用域的 a:', a)

func()
print('全域作用域的 a:', a)
修改前的 a: 2
閉合作用域的 a: 3       
全域作用域的 a: 1

注意:

# 全域作用域
a = 1

def func_1():
    # 在區域作用域定義 a 變數
    a = 2

def func_2():
    # 引入全域作用域的 a 變數并重新賦值
    global a
    a = 2

def func_3():
    # 嘗試對區域作用域的 a 變數進行自增操作
    # 由于此時 a 變數未定義則報錯
    a += 1

func_1()
func_2()
func_3()
Traceback (most recent call last):
  File "C:\Users\86177\Documents\1.py", line 20, in <module>
    func_3()
  File "C:\Users\86177\Documents\1.py", line 16, in func_3
    a += 1
UnboundLocalError: local variable 'a' referenced before assignment

python 會將在 func_3 的 a += 1 解釋為嘗試對區域作用域的 a 變數進行自增操作,由于此時 a 變數未定義會導致報錯,

2.3、命名空間與作用域的區別與聯系

  • 命名空間是一種實際的代碼實作,而作用域是程式設計上的一種規定,
  • 一個變數處在哪個命名空間則決定了它的作用域,而它的作用域則表示了它的作用范圍與被參考時所查找的順序優先級,

三、閉包

3.1、簡介

在 python 里萬物皆物件,函式也不例外,于是乎我們可以在一個函式中定義另一個函式作為回傳值,

def func(name):
    def wrapper():
        print(f'你好,{name}')

    return wrapper

result = func('小明')
result()
你好小明

閉包: f 函式中定義了 g 函式, g 還參考了 f 定義的變數, 就是閉包,
由作用域的查找規則可知,在這段代碼中,func 函式內是區域作用域, wrapper 函式內是閉合作用域, wrapper 函式可以直接使用 func 函式內的變數,

在實作閉包時,回傳的函式會帶有 __closure __屬性,在__closure __里可以找到函式所需要的變數,

print(result.__closure__) # 列印一下 __closure__ 屬性
print(result.__closure__[0].cell_contents) # 通過 cell_contents 可以得到保存的變數
(<cell at 0x00000201DE3664F0: str object at 0x00000201DE397A50>,)
小明

3.2、閉包的應用場景

使用閉包主要有以下三個好處:

  • 關聯資料與函式
  • 保存臨時變數,減少全域變數
  • 保存私有變數,防止變數被修改

3.2.1、關聯資料與函式

# 寫法 1:用類實作
class Timer:
    def __init__(self, base):
        self.base = base

    def time(self, x):
        return self.base * x

timer2 = Timer(2)
print('結果:', timer2.time(4))

# 寫法 2:用閉包實作
def timer(base):
    def wrapper(x):
        return x * base

    return wrapper

timer2 = timer(2)
print('結果:', timer2(4))
結果: 8
結果: 8

3.2.2、保存臨時變數

 # 寫法 1:將變數定義在全域作用域
count = 0

def func():
    global count
    count += 1
    print(f'執行了{count}次')

func()
func()

# 寫法 2:將變數定義在閉包中的區域作用域
def counter():
    count = 0

    def wrapper():
        nonlocal count
        count += 1
        print(f'執行了{count}次')

    return wrapper

func = counter()
func()
func()
執行了1次
執行了2次
執行了1次
執行了2

3.2.3、保存私有變數

def my_dict(**kwargs):
    def wrapper():
        # 這里是重新生成了一個字典物件,
        # 因為如果直接回傳則屬于淺拷貝,
        # 會導致外部仍能修改字典的值,
        return {**kwargs}

    return wrapper

xiaoming = my_dict(name='小明', age=18)

print('修改前:', xiaoming())
xiaoming()['name'] = '小紅'
print('修改后:', xiaoming())
修改前: {'name': '小明', 'age': 18}
修改后: {'name': '小明', 'age': 18}

四、裝飾器

4.1、函式裝飾器

在閉包中得知,函式是一個物件,

  • 能在函式中定義一個函式
  • 能作為引數傳遞
  • 能作為回傳值
def decorator(func):
    def wrapper(*args, **kwargs):
        print('123')
        return func(*args, **kwargs)

    return wrapper

def say_hello():
    print('同學你好')

say_hello_super = decorator(say_hello)
say_hello_super()
123
同學你好

在這段代碼中,我們將一個函式 say_hello 作為引數傳入函式 decorator,回傳一個wrapper 函式并賦值到 say_hello_super,此時執行 say_hello_super 相當于執行 wrapper 函式,當我們執行 wrapper 函式時會先列印123再執行先前傳入的 func 引數也就是 say_hello 函式,

裝飾器寫法:

def decorator(func):
    def wrapper(*args, **kwargs):
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello():
    print('同學你好')

say_hello()

這里在函式前加上 @decorator 相當于在定義函式后執行了一條陳述句, say_hello = decorator(say_hello) ,

4.2、帶引數的裝飾器

def info(value):
    def decorator(func):
        def wrapper(*args, **kwargs):
            print(value)
            return func(*args, **kwargs)

        return wrapper

    return decorator

@info('456')
def say_hello():
    print('同學你好')

say_hello()
456
同學你好

我們可以在裝飾器外部再套上一層函式,用該函式的引數接收我們想要列印的資料,并將先前的 decorator 函式作為回傳值,這就是之前學到的閉包的一種功能,就是用閉包來生成一個命名空間,在命名空間中保存我們要列印的值 value

4.3、wraps 裝飾器

一個函式不止有他的執行陳述句,還有著 __name__(函式名),__doc__(說明檔案)等屬性,我們之前的例子會導致這些屬性改變,

def decorator(func):
    def wrapper(*args, **kwargs):
        """doc of wrapper"""
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello():
    """doc of say hello"""
    print('同學你好')

print(say_hello.__name__)
print(say_hello.__doc__)
wrapper
doc of wrapper

由于裝飾器回傳了 wrapper 函式替換掉了之前的 say_hello 函式,導致函式名,幫助檔案變成了 wrapper 函式的了,

解決這一問題的辦法是通過 functools 模塊下的 wraps 裝飾器,

from functools import wraps

def decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """doc of wrapper"""
        print('123')
        return func(*args, **kwargs)

    return wrapper

@decorator
def say_hello():
    """doc of say hello"""
    print('同學你好')

print(say_hello.__name__)
print(say_hello.__doc__)
say_hello
doc of say hello

4.4、內置裝飾器

有三種我們經常會用到的裝飾器, propertystaticmethodclassmethod,他們有個共同點,都是作用于類方法之上,

4.4.1、property 裝飾器

property 裝飾器用于類中的函式,使得我們可以像訪問屬性一樣來獲取一個函式的回傳值,

class XiaoMing:
    first_name = '明'
    last_name = '小'

    @property
    def full_name(self):
        return self.last_name + self.first_name

xiaoming = XiaoMing()
print(xiaoming.full_name)
小明

我們像獲取屬性一樣獲取 full_name 方法的回傳值,這就是用property 裝飾器的意義,既能像屬性一樣獲取值,又可以在獲取值的時候做一些操作,

4.4.2、staticmethod 裝飾器

staticmethod 裝飾器同樣是用于類中的方法,這表示這個方法將會是一個靜態方法,意味著該方法可以直接被呼叫無需實體化,但同樣意味著它沒有 self引數,也無法訪問實體化后的物件,

class XiaoMing:
    @staticmethod
    def say_hello():
        print('同學你好')

XiaoMing.say_hello()

# 實體化呼叫也是同樣的效果
# 有點多此一舉
xiaoming = XiaoMing()
xiaoming.say_hello()
同學你好
同學你好

4.4.3、classmethod 裝飾器

classmethod 依舊是用于類中的方法,這表示這個方法將會是一個類方法,意味著該方法可以直接被呼叫無需實體化,但同樣意味著它沒有 self 引數,也無法訪問實體化后的物件,相對于 staticmethod 的區別在于它會接收一個指向類本身的 cls 引數

class XiaoMing:
    name = '小明'

    @classmethod
    def say_hello(cls):
        print('同學你好, 我是' + cls.name)
        print(cls)

XiaoMing.say_hello()
同學你好, 我是小明
<class '__main__.XiaoMing'>

4.5、類裝飾器

類能實作裝飾器的功能, 是由于當我們呼叫一個物件時,實際上呼叫的是它的 __call__ 方法,

class Demo:
    def __call__(self):
        print('我是 Demo')

demo = Demo()
demo()
我是 Demo

通過這個特性,我們便可以用類的方式來完成裝飾器,功能與剛開始用函式實作的一致,

class Decorator:
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print('123')
        return self.func(*args, **kwargs)

@Decorator
def say_hello():
    print('同學你好')

say_hello()
123
同學你好

比如說我們有一些計算耗時很長的函式,并且每次計算的結果不變,那么我們就可以通過類定義一個快取裝飾器,來快取第一次執行的結果,

import time

class Cache:
    __cache = {}

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

    def __call__(self):

        # 如果快取字典中有這個方法的執行結果
        # 直接回傳快取的值
        if self.func.__name__ in Cache.__cache:
            return Cache.__cache[self.func.__name__]

        # 計算方法的執行結果
        value = self.func()
        # 將其添加到快取
        Cache.__cache[self.func.__name__] = value
        # 回傳計算結果
        return value

@Cache
def long_time_func():
    time.sleep(5)
    return '我是計算結果'

start = time.time()
print(long_time_func())
end = time.time()
print(f'計算耗時{end-start}秒')

start = time.time()
print(long_time_func())
end = time.time()
print(f'計算耗時{end-start}秒')
我是計算結果
計算耗時5.009094476699829秒
我是計算結果
計算耗時0.0

實作一個裝飾器,能夠計算函式的執行耗時,

import time

def calc(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f'{func.__name__}函式執行耗時{end-start}秒,')
        return result

    return wrapper

@calc
def count_2():
    for i in range(0, 2):
        print(f'第{i+1}次計數')
        time.sleep(1)  # 暫停一秒鐘

@calc
def count_5():
    for i in range(0, 5):
        print(f'第{i+1}次計數')
        time.sleep(1)  # 暫停一秒鐘

count_2()
count_5()
1次計數
第2次計數
count_2函式執行耗時2.0178287029266357秒,
第1次計數
第2次計數
第3次計數
第4次計數
第5次計數
count_5函式執行耗時5.0245983600616455秒,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/289808.html

標籤:python

上一篇:【小白學Java】D27》》》程式的例外處理 try - catch & throw & throws& 自定義例外

下一篇:流媒體服務新手入門教程01--什么是流媒體服務及m7s介紹

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more