0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Python中變量在內(nèi)存中的存儲(chǔ)方式

馬哥Linux運(yùn)維 ? 來源:博客園TsayDust ? 2024-07-16 16:29 ? 次閱讀

Python類方法vs靜態(tài)方法

類方法(Class Methods)

類方法使用@classmethod裝飾器定義,它們的第一個(gè)參數(shù)通常命名為cls,代表類本身。

特點(diǎn):

可以訪問和修改類的狀態(tài)

不能訪問實(shí)例的狀態(tài)

可以用來定義替代構(gòu)造器

示例:

class MyClass:
    class_variable = 0

    @classmethod
    def increment_class_variable(cls):
        cls.class_variable += 1

    @classmethod
    def from_string(cls, string_param):
        # 替代構(gòu)造器
        return cls(int(string_param))

# 使用類方法
MyClass.increment_class_variable()
obj = MyClass.from_string("10")

靜態(tài)方法(Static Methods)

靜態(tài)方法使用@staticmethod裝飾器定義,它們不接收任何特殊的第一個(gè)參數(shù)。

特點(diǎn):

不能訪問或修改類的狀態(tài)

不能訪問實(shí)例的狀態(tài)

主要用于將功能邏輯組織到類中

示例:

class MathOperations:
    @staticmethod
    def add(x, y):
        return x + y

    @staticmethod
    def multiply(x, y):
        return x * y

# 使用靜態(tài)方法
result = MathOperations.add(5, 3)

主要區(qū)別

參數(shù):類方法接收類作為隱式第一個(gè)參數(shù),靜態(tài)方法不接收特殊參數(shù)。

訪問類屬性:類方法可以訪問和修改類屬性,靜態(tài)方法不能。

使用場景

類方法通常用于需要訪問類狀態(tài)的操作,如替代構(gòu)造器。

靜態(tài)方法用于與類相關(guān)但不需要訪問類狀態(tài)的操作。

繼承行為:子類繼承類方法時(shí),cls參數(shù)會(huì)指向子類。靜態(tài)方法的行為在繼承時(shí)不變。

選擇使用哪種方法

如果方法需要訪問類屬性或者修改類狀態(tài),使用類方法。

如果方法不需要訪問類或?qū)嵗隣顟B(tài),只是提供一些相關(guān)功能,使用靜態(tài)方法。

如果方法既不需要訪問類狀態(tài)也不需要訪問實(shí)例狀態(tài),但從邏輯上屬于類,使用靜態(tài)方法。

Python中的深拷貝與淺拷貝

在Python中,當(dāng)我們復(fù)制對象時(shí),有兩種主要的方式:深拷貝(Deep Copy)和淺拷貝(Shallow Copy)。理解這兩者的區(qū)別對于正確處理復(fù)雜數(shù)據(jù)結(jié)構(gòu)非常重要。

淺拷貝(Shallow Copy)

淺拷貝創(chuàng)建一個(gè)新對象,但是它包含的元素是原始對象中元素的引用。

特點(diǎn):

創(chuàng)建一個(gè)新對象

新對象中的元素是原始對象元素的引用

只復(fù)制對象的第一層

實(shí)現(xiàn)方式:

使用切片操作[:]

使用copy()方法

使用copy模塊的copy()函數(shù)

示例:

import copy

original = [1, [2, 3], 4]
shallow = copy.copy(original)

# 修改淺拷貝中的嵌套列表
shallow[1][0] = 'X'

print(original)  # 輸出: [1, ['X', 3], 4]
print(shallow)   # 輸出: [1, ['X', 3], 4]

在這個(gè)例子中,修改淺拷貝中的嵌套列表也會(huì)影響原始列表。

深拷貝(Deep Copy)

深拷貝創(chuàng)建一個(gè)新對象,并遞歸地復(fù)制原始對象中的所有嵌套對象。

特點(diǎn):

創(chuàng)建一個(gè)全新的對象

遞歸地復(fù)制所有嵌套的對象

原始對象和拷貝對象完全獨(dú)立

實(shí)現(xiàn)方式:

使用copy模塊的deepcopy()函數(shù)

示例:

import copy

original = [1, [2, 3], 4]
deep = copy.deepcopy(original)

# 修改深拷貝中的嵌套列表
deep[1][0] = 'X'

print(original)  # 輸出: [1, [2, 3], 4]
print(deep)      # 輸出: [1, ['X', 3], 4]

在這個(gè)例子中,修改深拷貝中的嵌套列表不會(huì)影響原始列表。

主要區(qū)別

復(fù)制深度:淺拷貝只復(fù)制對象的第一層,而深拷貝遞歸地復(fù)制所有層。

內(nèi)存使用:深拷貝通常比淺拷貝使用更多的內(nèi)存,因?yàn)樗鼊?chuàng)建了所有嵌套對象的副本。

性能:深拷貝通常比淺拷貝慢,特別是對于大型或復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。

獨(dú)立性:深拷貝創(chuàng)建的對象與原始對象完全獨(dú)立,而淺拷貝創(chuàng)建的對象與原始對象共享部分?jǐn)?shù)據(jù)。

使用場景

使用淺拷貝:當(dāng)您只需要復(fù)制對象的頂層,而且嵌套對象可以共享時(shí)。

使用深拷貝:當(dāng)您需要?jiǎng)?chuàng)建一個(gè)完全獨(dú)立的副本,包括所有嵌套對象時(shí)。

注意事項(xiàng)

對于不可變對象(如元組),淺拷貝和深拷貝的行為是相同的。

循環(huán)引用可能會(huì)導(dǎo)致深拷貝出現(xiàn)問題,deepcopy()函數(shù)有處理這種情況的機(jī)制。

自定義類可以通過實(shí)現(xiàn)__copy__()和__deepcopy__()方法來控制復(fù)制行為。

Python裝飾器詳解

裝飾器是Python中的一種高級功能,允許您修改或增強(qiáng)函數(shù)或類的行為,而無需直接修改其源代碼。

基本概念

裝飾器本質(zhì)上是一個(gè)函數(shù),它接受一個(gè)函數(shù)作為參數(shù),并返回一個(gè)新的函數(shù)。

基本語法

@decorator_function
def target_function():
    pass

這等同于:

def target_function():
    pass
target_function = decorator_function(target_function)

簡單裝飾器示例

1. 函數(shù)裝飾器

def uppercase_decorator(func):
    def wrapper():
        result = func()
        return result.upper()
    return wrapper

@uppercase_decorator
def greet():
    return "hello, world!"

print(greet())  # 輸出:HELLO, WORLD!

2. 帶參數(shù)的裝飾器

def repeat_decorator(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat_decorator(3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")  # 將打印 3 次 "Hello, Alice!"

裝飾器的高級用法

1. 類作為裝飾器

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0
    
    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        print(f"Call {self.num_calls} of {self.func.__name__!r}")
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

say_hello()
say_hello()

2. 保留原函數(shù)的元數(shù)據(jù)

使用functools.wraps裝飾器來保留被裝飾函數(shù)的元數(shù)據(jù):

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        """Wrapper function"""
        print('Before call')
        result = func(*args, **kwargs)
        print('After call')
        return result
    return wrapper

@my_decorator
def greet(name):
    """Greet someone"""
    print(f"Hello, {name}!")

print(greet.__name__)  # 輸出:greet
print(greet.__doc__)   # 輸出:Greet someone

裝飾器的常見應(yīng)用

日志記錄

性能測量

訪問控制和認(rèn)證

緩存

錯(cuò)誤處理和重試邏輯

注意事項(xiàng)

裝飾器在函數(shù)定義時(shí)就會(huì)執(zhí)行,而不是在函數(shù)調(diào)用時(shí)。

多個(gè)裝飾器可以堆疊使用,執(zhí)行順序是從下到上。

裝飾器可能會(huì)影響函數(shù)的性能,特別是在頻繁調(diào)用的情況下。

使用functools.wraps可以保留被裝飾函數(shù)的元數(shù)據(jù)。

裝飾器的實(shí)現(xiàn)原理

裝飾器的實(shí)現(xiàn)原理涉及到Python的幾個(gè)重要概念:函數(shù)是一等公民、閉包、以及Python的語法糖。讓我們逐步分解裝飾器的實(shí)現(xiàn)過程:

1. 函數(shù)作為一等公民

在Python中,函數(shù)是一等公民,這意味著函數(shù)可以:

賦值給變量

作為參數(shù)傳遞給其他函數(shù)

作為其他函數(shù)的返回值

這是裝飾器實(shí)現(xiàn)的基礎(chǔ)。

2. 閉包

閉包是一個(gè)函數(shù),它記住了創(chuàng)建它時(shí)的環(huán)境。在Python中,內(nèi)部函數(shù)可以訪問外部函數(shù)的變量,這就創(chuàng)建了一個(gè)閉包。

3. 裝飾器的基本實(shí)現(xiàn)

讓我們通過一個(gè)簡單的例子來說明裝飾器的實(shí)現(xiàn):

def simple_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

def say_hello():
    print("Hello!")

say_hello = simple_decorator(say_hello)

在這個(gè)例子中:

simple_decorator是一個(gè)函數(shù),它接受一個(gè)函數(shù)作為參數(shù)。

在simple_decorator內(nèi)部,我們定義了一個(gè)新的函數(shù)wrapper。

wrapper函數(shù)在調(diào)用原始函數(shù)前后添加了一些行為。

simple_decorator返回wrapper函數(shù)。

最后,我們用simple_decorator返回的新函數(shù)替換了原始的say_hello函數(shù)。

4. 語法糖

Python提供了一個(gè)語法糖(@符號(hào))來簡化裝飾器的使用:

@simple_decorator
def say_hello():
    print("Hello!")

這等同于前面的例子,但更加簡潔和易讀。

5. 帶參數(shù)的裝飾器

帶參數(shù)的裝飾器實(shí)際上是一個(gè)返回裝飾器的函數(shù):

def repeat(times):
    def decorator(func):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = func(*args, **kwargs)
            return result
        return wrapper
    return decorator

@repeat(3)
def say_hello(name):
    print(f"Hello, {name}!")

這里,repeat函數(shù)返回一個(gè)裝飾器,該裝飾器然后被應(yīng)用到say_hello函數(shù)上。

6. 類裝飾器

類裝飾器利用了Python的__call__方法,使得類的實(shí)例可以像函數(shù)一樣被調(diào)用:

class CountCalls:
    def __init__(self, func):
        self.func = func
        self.num_calls = 0
    
    def __call__(self, *args, **kwargs):
        self.num_calls += 1
        return self.func(*args, **kwargs)

@CountCalls
def say_hello():
    print("Hello!")

7. 裝飾器的執(zhí)行時(shí)機(jī)

重要的是要理解,裝飾器在函數(shù)定義時(shí)就會(huì)執(zhí)行,而不是在函數(shù)調(diào)用時(shí)。這意味著裝飾器可以在模塊導(dǎo)入時(shí)就改變函數(shù)的行為。

8. 多個(gè)裝飾器

當(dāng)多個(gè)裝飾器應(yīng)用到一個(gè)函數(shù)上時(shí),它們的執(zhí)行順序是從下到上的:

@decorator1
@decorator2
def func():
    pass

這等同于:

func = decorator1(decorator2(func))

通過理解這些原理,我們可以看到裝飾器如何利用Python的函數(shù)特性和語法來實(shí)現(xiàn)強(qiáng)大而靈活的代碼修改和增強(qiáng)功能。

Python中變量在內(nèi)存中的存儲(chǔ)方式

Python的內(nèi)存管理是一個(gè)復(fù)雜的主題,但了解它可以幫助我們寫出更高效的代碼。讓我們逐步探討Python中變量的存儲(chǔ)方式。

1. 變量和對象的關(guān)系

在Python中,變量本質(zhì)上是對對象的引用。當(dāng)我們創(chuàng)建一個(gè)變量時(shí),我們實(shí)際上是在內(nèi)存中創(chuàng)建了一個(gè)對象,然后將變量名與該對象的內(nèi)存地址關(guān)聯(lián)起來。

x = 5

在這個(gè)例子中,Python在內(nèi)存中創(chuàng)建了一個(gè)整數(shù)對象5,然后將變量名x與這個(gè)對象的地址關(guān)聯(lián)起來。

2. 對象的內(nèi)存表示

Python中的每個(gè)對象至少包含三個(gè)部分:

類型標(biāo)識(shí)符(告訴Python這個(gè)對象是什么類型)

引用計(jì)數(shù)(用于垃圾回收)

3. 不同類型對象的存儲(chǔ)

小整數(shù)

Python對小整數(shù)(通常是-5到256)進(jìn)行了優(yōu)化。這些整數(shù)被預(yù)先創(chuàng)建并緩存,所有對這些值的引用都指向同一個(gè)對象。

a = 5
b = 5
print(a is b)  # 輸出:True

大整數(shù)

對于大整數(shù),每次賦值都會(huì)創(chuàng)建一個(gè)新的對象。

a = 1000
b = 1000
print(a is b)  # 輸出:False

字符串

Python也對字符串進(jìn)行了優(yōu)化。相同內(nèi)容的字符串通常會(huì)指向同一個(gè)對象(這被稱為字符串駐留)。

a = "hello"
b = "hello"
print(a is b)  # 輸出:True

可變對象(如列表)

可變對象每次創(chuàng)建時(shí)都會(huì)在內(nèi)存中分配新的空間。

a = [1, 2, 3]
b = [1, 2, 3]
print(a is b)  # 輸出:False

4. 變量賦值

當(dāng)我們進(jìn)行變量賦值時(shí),我們實(shí)際上是改變變量引用的對象。

x = 5  # x 引用整數(shù)對象 5
x = 10  # x 現(xiàn)在引用整數(shù)對象 10,而不是修改原來的 5

5. 引用計(jì)數(shù)和垃圾回收

Python使用引用計(jì)數(shù)來進(jìn)行內(nèi)存管理。每個(gè)對象都有一個(gè)引用計(jì)數(shù),表示有多少個(gè)變量引用了這個(gè)對象。當(dāng)引用計(jì)數(shù)降為0時(shí),對象就會(huì)被垃圾回收器回收。

x = 5  # 創(chuàng)建整數(shù)對象 5,引用計(jì)數(shù)為 1
y = x  # y 也引用同一個(gè)對象,引用計(jì)數(shù)增加到 2
del x  # 刪除 x,引用計(jì)數(shù)減少到 1
# y 仍然引用這個(gè)對象

6. 內(nèi)存視圖

我們可以使用id()函數(shù)來查看對象的內(nèi)存地址:

x = 5
print(id(x))  # 輸出對象的內(nèi)存地址

7. 可變對象vs不可變對象

不可變對象(如整數(shù)、字符串、元組):當(dāng)這些對象的"值"改變時(shí),實(shí)際上是創(chuàng)建了一個(gè)新對象。

可變對象(如列表、字典):這些對象可以在原地修改,不需要?jiǎng)?chuàng)建新對象。

# 不可變對象
x = 5
print(id(x))
x += 1
print(id(x))  # 地址會(huì)改變

# 可變對象
lst = [1, 2, 3]
print(id(lst))
lst.append(4)
print(id(lst))  # 地址不會(huì)改變

理解Python的內(nèi)存管理和變量存儲(chǔ)方式可以幫助我們寫出更高效的代碼,并避免一些常見的陷阱。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    2952

    瀏覽量

    73738
  • 變量
    +關(guān)注

    關(guān)注

    0

    文章

    609

    瀏覽量

    28289
  • python
    +關(guān)注

    關(guān)注

    54

    文章

    4759

    瀏覽量

    84296

原文標(biāo)題:Python中變量在內(nèi)存中的存儲(chǔ)方式

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    小數(shù)在內(nèi)存是如何存儲(chǔ)的?為什么C語言中的浮點(diǎn)數(shù)不支持位移操作?

    小數(shù)在內(nèi)存是如何存儲(chǔ)的?為什么C語言中的浮點(diǎn)數(shù)不支持位移操作?
    發(fā)表于 08-16 09:24 ?955次閱讀
    小數(shù)<b class='flag-5'>在內(nèi)存</b><b class='flag-5'>中</b>是如何<b class='flag-5'>存儲(chǔ)</b>的?為什么C語言中的浮點(diǎn)數(shù)不支持位移操作?

    各種變量在內(nèi)存的位置有何不同

    各種變量在內(nèi)存的位置有何不同?怎樣使用交叉變壓器將轉(zhuǎn)換語言分類的翻譯呢?
    發(fā)表于 10-22 09:33

    數(shù)據(jù)在內(nèi)存存儲(chǔ)形式(大小端模式)的介紹與判定

    數(shù)據(jù)在內(nèi)存存儲(chǔ)形式(大小端模式)的介紹與判定(C語言實(shí)習(xí))
    發(fā)表于 01-20 08:26

    2.1 python常量與變量

    2.1 python常量與變量變量:在程序運(yùn)行過程,值會(huì)發(fā)生變化的量常量:在程序運(yùn)行過程,值不會(huì)發(fā)生變化的量無論是變量還是常量,在創(chuàng)建時(shí)
    發(fā)表于 02-16 18:34

    詳細(xì)解讀Python變量類型

    變量存儲(chǔ)在內(nèi)存的值。這就意味著在創(chuàng)建變量時(shí)會(huì)在內(nèi)存
    的頭像 發(fā)表于 10-17 17:14 ?2646次閱讀
    詳細(xì)解讀<b class='flag-5'>Python</b><b class='flag-5'>變量</b>類型

    單片機(jī)的程序在內(nèi)存和FLASH應(yīng)該如何進(jìn)行空間分配

    一句話:基于速度問題,電腦使用硬盤存儲(chǔ)程序,運(yùn)行時(shí),在內(nèi)存中分配空間給變量,加載程序到內(nèi)存,在內(nèi)存
    發(fā)表于 09-18 17:20 ?3次下載
    單片機(jī)的程序<b class='flag-5'>在內(nèi)存</b>和FLASH<b class='flag-5'>中</b>應(yīng)該如何進(jìn)行空間分配

    Python變量類型詳細(xì)資料說明

    Python 變量賦值不需要類型聲明。每個(gè)變量在內(nèi)存創(chuàng)建,都包括
    發(fā)表于 08-24 16:47 ?3次下載
    <b class='flag-5'>Python</b>的<b class='flag-5'>變量</b>類型詳細(xì)資料說明

    浮點(diǎn)數(shù)在內(nèi)存存儲(chǔ)

    浮點(diǎn)數(shù)在內(nèi)存存儲(chǔ)和整數(shù)不同,因?yàn)檎麛?shù)都可以轉(zhuǎn)換為一一對應(yīng)的二進(jìn)制數(shù)據(jù)。而浮點(diǎn)數(shù)的存儲(chǔ)是由符號(hào)位 (sign) + 指數(shù)位 (exponent) + 小數(shù)位 (fraction) 組
    的頭像 發(fā)表于 09-20 10:52 ?3986次閱讀
    浮點(diǎn)數(shù)<b class='flag-5'>在內(nèi)存</b><b class='flag-5'>中</b>的<b class='flag-5'>存儲(chǔ)</b>

    Python變量類型詳細(xì)說明

    變量賦值Python 變量賦值不需要類型聲明。 每個(gè)變量在內(nèi)存
    發(fā)表于 01-15 16:29 ?1次下載
    <b class='flag-5'>Python</b>的<b class='flag-5'>變量</b>類型詳細(xì)說明

    char *s和char s[]在內(nèi)存是怎么存儲(chǔ)的?

    從語法層面上講,上面的是指針,下面的是數(shù)組,但是想要搞清楚他們的區(qū)別,還得知道他們在內(nèi)存怎么存儲(chǔ)的。
    的頭像 發(fā)表于 02-13 09:45 ?1820次閱讀

    Python-變量的引用與可變

    變量和數(shù)據(jù)都是保存在內(nèi)存的,在Python,函數(shù)的參數(shù)傳遞和返回值都是靠引用傳遞的
    的頭像 發(fā)表于 02-16 15:15 ?728次閱讀
    <b class='flag-5'>Python</b>-<b class='flag-5'>變量</b>的引用與可變

    變量存儲(chǔ)

    在編寫C程序的過程,我們常常會(huì)使用到變量。而基本的變量類型在前面的教程也已經(jīng)講到,在我們創(chuàng)建這些變量的時(shí)候,變量會(huì)被創(chuàng)建
    的頭像 發(fā)表于 02-21 15:07 ?722次閱讀
    <b class='flag-5'>變量</b>的<b class='flag-5'>存儲(chǔ)</b>

    什么是堆內(nèi)存?存儲(chǔ)方式是什么樣的?

    存儲(chǔ)方式。 C 代碼動(dòng)態(tài)申請堆內(nèi)存的申請函數(shù)是 malloc ,常見的內(nèi)存代碼如下圖所示: 因?yàn)閙alloc函數(shù)返回值是一個(gè)
    的頭像 發(fā)表于 06-22 10:29 ?1096次閱讀
    什么是堆<b class='flag-5'>內(nèi)存</b>?<b class='flag-5'>存儲(chǔ)</b><b class='flag-5'>方式</b>是什么樣的?

    python變量命名規(guī)則

    Python是一種高級編程語言,廣泛應(yīng)用于軟件開發(fā)、數(shù)據(jù)分析和科學(xué)計(jì)算等領(lǐng)域。在Python,變量是用來存儲(chǔ)數(shù)據(jù)的容器,它們具有名稱以及與
    的頭像 發(fā)表于 11-23 15:44 ?1128次閱讀

    數(shù)組和鏈表在內(nèi)存的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)

    數(shù)組和鏈表在內(nèi)存的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)? 數(shù)組和鏈表是常見的數(shù)據(jù)結(jié)構(gòu),用于組織和存儲(chǔ)數(shù)據(jù)。它們在內(nèi)存
    的頭像 發(fā)表于 02-21 11:30 ?779次閱讀