簡體   English   中英

類成員變量不是和全局變量一樣糟糕嗎?

[英]Aren't class member varialbes as bad as global variable?

由於使用了全局變量,我們都知道下面的代碼很糟糕:

a = 3.14

def inc():
  global a
  a += 1

inc()
b = a

太糟糕了,在 python 中,必須故意聲明 global 以“打破”禁令。 但是以 OO 的名義,下面的代碼怎么是有道理的:

class A:
  def __init__(self):
    self.a = 3.14

  def inc(self):
    self.a += 1

A_instance = A()
A_instance.inc()
b = A_instance.a

在類實例的范圍內,成員變量不就是和全局變量一樣嗎? “self”基本上允許任何成員函數不受限制地訪問所有變量,而不管其必要性,使其非常有狀態,容易出錯,並且難以閱讀(基本上是全局變量的所有不良特征)?

我們也知道干凈和更好的方法是:

def inc(_a):
  return _a+1

a = 3.14
b = inc(a)

這樣函數 inc() 至少是無狀態的並且具有可預測的行為。 使用類並使其盡可能無狀態的最佳實踐是什么? 或者根據定義,OO 是否總是有狀態的,並且必須完全不使用類進行函數式編程? 我也聽人說@static 方法很笨,破壞封裝,應該避免......

現在self的概念不被認為是不好的做法的原因是,如果您要創建一個類,該類中的所有內容都應該以一種或另一種方式相關,這通常是通過__init__ dunder 初始化類實例的類屬性方法。 基本上,如果您要創建一個類,那么應該有某種鏈接,如果您願意,則應該有一個全局類,這些類是類屬性

通常的想法是像這樣用self創建類

class A:
  def __init__(self):
    self.a = 3.14

  def inc(self):
    self.a += 1

不是經常看到的東西,而是人們選擇了在許多觀點中通常被認為更清潔和更可預測的方式

class A:
  def __init__(self, a):
    self.a = a

  def inc(self):
    self.a += 1

有了這個,當您聲明類實例時,您可以更好地控制實際存在的內容,因此類實例用變量聲明

A_instance = A(3.14)   #a will be 3.14 in this instance
B_instance = A(3.142)  #a will be 3.142 in this instance

等等。 __init__函數外部聲明但在類內部聲明的類變量本身有很大不同,看起來像

class A:
  a = 22/7

  def __init__(self):
      ....

有了這個a將是整個類中的全局變量(不是實例而是類本身)。 那看起來像什么

class A:
    a = 22/7

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

A_instance = A(3.14)
B_instance = A(5)

盡管A_instanceB_instance是完全不同的, A_instance.item將等於3.14B_instance.item將等於5這兩個都將具有類變量a22/7

A_instance.a  #this will return a value of 22/7
B_instance.a  #this will also return a value of 22/7

因此,除非主動更改,否則類變量在該類的所有實例中保持一致/相同。

要點是,如果您要創建一個類,它應該具有相互交織的特定變量並影響所有特定組的函數,這些是您將函數放入類方法中,因此在類中使用self並沒有錯如果使用得當

這歸結為您是否需要保存狀態。 如果您確實需要保存狀態,則需要將其保存在某處。 類允許您將狀態與對該狀態進行操作的方法一起保存,並強制實施一個類本地范圍,該范圍比將狀態存儲在全局范圍內更不容易出錯。

作為一個具體的例子,我最近為森林模擬實現了一個 Tree 類。 與樹相關聯的重要變量之一是它的年齡。 樹的年齡應該存儲在哪里? 將其存儲在 Tree 類中比將其存儲在外部更有意義。

如果防止樹的年齡被類外的代碼操縱很重要,我可以為此目的使用 Python 出色的@property語法,或者不直接通過 Python _varname變量命名約定。

在類中,是的,樹的年齡對其他方法是可見的,但這是一個相對狹窄的范圍,如果您的類是按照 SOLID 面向對象設計原則編寫的單一職責,那么肯定不類似於全局范圍.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM