主頁 > 後端開發 > PEP 526 變數注解的語法 -- Python官方檔案譯文 [原創]

PEP 526 變數注解的語法 -- Python官方檔案譯文 [原創]

2020-10-17 10:22:25 後端開發

PEP 526 -- 變數注解的語法(Syntax for Variable Annotations)

英文原文:https://www.python.org/dev/peps/pep-0526
采集日期:2020-02-27

PEP: 526
Title: Syntax for Variable Annotations
Author: Ryan Gonzalez [email protected], Philip House [email protected], Ivan Levkivskyi [email protected], Lisa Roach [email protected], Guido van Rossum [email protected]
Status: Final
Type: Standards Track
Created: 09-Aug-2016
Python-Version: 3.6
Post-History: 30-Aug-2016, 02-Sep-2016
Resolution: https://mail.python.org/pipermail/python-dev/2016-September/146282.html

目錄

  • 重要程度(Status)
  • 評論者的注意事項(Notice for Reviewers)
  • 摘要(Abstract)
  • 原由(Rationale)
    • 非本文目標(Non-goals)
  • 規范(Specification)
    • 全域和區域變數的注解(Global and local variable annotations)
    • 類和實體變數的注解(Class and instance variable annotations)
    • 運算式的注解(Annotating expressions)
    • 注解允許出現的位置(Where annotations aren't allowed)
    • 存根檔案中的變數注解(Variable annotations in stub files)
    • 變數注解的推薦編碼風格(Preferred coding style for variable annotations)
  • 標準庫和檔案的改動(Changes to Standard Library and Documentation)
  • 型別注解的運行時效果(Runtime Effects of Type Annotations)
    • 注解的其他用途(Other uses of annotations)
  • 被拒絕/擱置的提案(Rejected/Postponed Proposals)
  • 向下兼容性(Backwards Compatibility)
  • 實作代碼(Implementation)
  • 著作權(Copyright)

重要程度(Status)


本 PEP 暫時已被 BDFL 收錄,更多觀點請參閱收錄資訊,

評論者的注意事項(Notice for Reviewers)


本 PEP 是在單獨的 repo 中起草的:https://github.com/phouse512/peps/tree/pep-0526,

初步的討論位于 python-ideas 和 https://github.com/python/typing/issues/258 上,

若要在公共論壇上提出異議,至少請先閱讀一下本 PEP 最后列出的被拒絕提議的主要內容,

摘要(Abstract)


PEP 484 引入了型別提示(type hint),又稱型別注解(type annotation),盡管其重點是函式注解,但也引入了型別注釋(type comment)的概念用于注解變數:

  # 'primes' is a list of integers
  primes = []  # type: List[int]

  # 'captain' is a string (Note: initial value is a problem)
  captain = ...  # type: str

  class Starship:
      # 'stats' is a class variable
      stats = {}  # type: Dict[str, int]

本文旨在為 Python 添加一種語法,用于對變數(包括類變數和實體變數)的型別做出注解,以取代通過注釋(comment)來表達型別的方式:

  primes: List[int] = []

  captain: str  # Note: no initial value!

  class Starship:
      stats: ClassVar[Dict[str, int]] = {}

PEP 484 明確指出型別注釋旨在幫助復雜情況下的型別推斷,本 PEP 不會改變此意圖,但實際情況是類變數和實體變數也用到了型別注釋,因此本 PEP 還討論了為這些變數添加型別注解的用法,

原由(Rationale)


盡管型別注釋已經夠用了,但也表現出一些缺點:

  • 文本編輯器經常會將注釋高亮顯示為型別注解不同的方式,

  • 無法為未定義變數添加型別注釋,需將其初始化為 None(例如 a = None # type: int

  • 條件分支陳述句內的變數注釋可讀性不好:

    if some_value:
        my_var = function() # type: Logger
    else:
        my_var = another_function() # Why isn't there a type here?
  • 因為型別注釋其實不是語言的組成部分,如果 Python 代碼要對其進行決議,就需要自定義決議程式,而不能只用 ast(Abstract Syntax Tree,抽象語法樹) 解決,

  • 型別注釋已大量應用于 typeshed 中,將 typeshed 遷移為采用變數注解的語法,替換掉型別注釋,可以提高存根檔案的可讀性,

  • 在混合使用普通注釋和型別注釋的場合,要做出區分是比較困難的:

    path = None  # type: Optional[str]  # Path to module source
  • 除了嘗試查看模塊的源代碼并在運行時進行決議,就再無他法在運行時讀取注解資訊了,至少可以認為這種做法不夠優雅,

通過讓注解語法成為語言的核心內容,可以緩解上述大多數問題,此外,作為由 PEP 484 定義的名稱定型(nominal typing)的補充,專用于類和實體變數(方法注解)的注解語法將為靜態鴨子定型鋪平道路,

非本文目標(Non-goals)


雖然本提案和用于運行時讀取注解資訊的標準庫函式 typing.get_type_hints 擴展一起出現,但變數注解并不是為運行時型別檢查而設計的,必須開發第三方軟體包才能實作該型別檢查功能,

還應該強調的是,**Python 仍將是一種動態定型語言,并且按慣例作者不希望讓型別提示成為強制要求,型別注解不應與靜態定型語言中的變數宣告相混淆,注解語法旨在為第三方工具提供一種簡便的方法,用于定義結構化型別的元資料,

本 PEP 不需要型別檢查程式改變其型別檢查規則,這里只是提供了一種可讀性更好的語法,以便替換型別注釋,

規范(Specification)


可以在一條賦值陳述句或某個運算式中加入型別注解,以向第三方型別檢查程式標示出被注解物件的應有型別:

  my_var: int
  my_var = 5  # Passes type check.
  other_var: int  = 'a'  # Flagged as error by type checker,
                         # but OK at runtime.

上述運算式并沒有引入超過 PEP 484 范圍的新語意,因此以下三條陳述句是等效的:

  var = value # type: annotation
  var: annotation; var = value
  var: annotation = value

下面給出各種背景關系環境中的型別注解語法定義,以及運行時的效果,

同時給出了型別檢查程式對注釋的決議建議,但這些建議不是必須遵守的,這符合 PEP 484 對合規性的態度,

全域和區域變數的注解(Global and local variable annotations)


區域和全域變數的型別可以如下做出注解:

  some_number: int           # variable without initial value
  some_list: List[int] = []  # variable with initial value

省略初始值能讓條件分支陳述句中的變數更容易定型:

  sane_world: bool
  if 2+2 == 4:
      sane_world = True
  else:
      sane_world = False

注意,盡管語法上確實允許元組打包時帶上注解,但在采用元組解包寫法時允許注解變數的型別,

  # Tuple packing with variable annotation syntax
  t: Tuple[int, ...] = (1, 2, 3)
  # or
  t: Tuple[int, ...] = 1, 2, 3  # This only works in Python 3.8+

  # Tuple unpacking with variable annotation syntax
  header: str
  kind: int
  body: Optional[List[str]]
  header, kind, body = message

若省略初始值,則變數為未初始化狀態:

  a: int
  print(a)  # raises NameError

如果給區域變數加上注解,則會讓解釋器一直將其視為區域變數:

  def f():
      a: int
      print(a)  # raises UnboundLocalError
      # Commenting out the a: int makes it a NameError.

以下代碼也是一樣:

  def f():
      if False: a = 0
      print(a)  # raises UnboundLocalError

重復的型別注解將被忽略,但靜態型別檢查程式可以發出一條警告資訊,提示同一個變數注解為不同型別:

  a: int
  a: str  # Static type checker may or may not warn about this.

類和實體變數的注解(Class and instance variable annotations)


型別注解也可在類和方法內部用于為類和實體變數加上注解,特別是 a: int 這種不給出值的注解,使得應在 __init____new__ 中進行初始化的實體變數也能加上注解,建議語法如下:

  class BasicStarship:
      captain: str = 'Picard'               # instance variable with default
      damage: int                           # instance variable without default
      stats: ClassVar[Dict[str, int]] = {}  # class variable

以上的 ClassVar 是一個由 typing 模塊定義的特殊類,向靜態型別檢查程式標示在實體中不允許對該變數進行賦值,

請注意,無論嵌套多少層,ClassVar 的引數中都不能包含任何型別變數:如果 T 是型別變數的話,ClassVar[T]ClassVar[List[Set[T]]] 都是非法的,

用個更詳細的例子來演示一下吧,

  class Starship:
      captain = 'Picard'
      stats = {}

      def __init__(self, damage, captain=None):
          self.damage = damage
          if captain:
              self.captain = captain  # Else keep the default

      def hit(self):
          Starship.stats['hits'] = Starship.stats.get('hits', 0) + 1

在以上類中,stats 應該是一個類變數(用于記錄每局游戲的各種狀態),而 captain 則是一個默認值由類設定的實體變數,型別檢查程式可能發現不了這兩者的差異:兩者都在類中進行了初始化,但 captain 僅作為便于實體變數使用的默認值,而 stats 則真是打算讓所有實體共享的類變數,

由于兩個變數恰好都在類這個級別進行了初始化,因此將類變數標記為以 ClassVar[...] 包裹的型別注釋,對區分他們是很有用的,這樣若對實體中同名屬性發生意外賦值,型別檢查程式就可以做出標記,

比如對上述類加上以下注解:

  class Starship:
      captain: str = 'Picard'
      damage: int
      stats: ClassVar[Dict[str, int]] = {}

      def __init__(self, damage: int, captain: str = None):
          self.damage = damage
          if captain:
              self.captain = captain  # Else keep the default

      def hit(self):
          Starship.stats['hits'] = Starship.stats.get('hits', 0) + 1

  enterprise_d = Starship(3000)
  enterprise_d.stats = {} # Flagged as error by a type checker
  Starship.stats = {} # This is OK

為了方便使用和遵循慣例,實體變數可以在 __init__ 或其他方法中進行注解,而不是在類中進行:

  from typing import Generic, TypeVar
  T = TypeVar('T')

  class Box(Generic[T]):
      def __init__(self, content):
          self.content: T = content

運算式的注解(Annotating expressions)


注解的物件可以是任一合法的可賦值物,至少在語法上是如此的(視型別檢查程式采取的對策而定):

  class Cls:
      pass

  c = Cls()
  c.x: int = 0  # Annotates c.x with int.
  c.y: int      # Annotates c.y with int.

  d = {}
  d['a']: int = 0  # Annotates d['a'] with int.
  d['b']: int      # Annotates d['b'] with int.

請注意,雖然帶括號的變數名也被視為運算式,但其不是簡單名稱(simple name):

  (x): int      # Annotates x with int, (x) treated as expression by compiler.
  (y): int = 0  # Same situation here.

注解允許出現的位置(Where annotations aren't allowed)


在函式同級作用域內將變數注解為 globalnonlocal 是非法操作,

  def f():
      global x: int  # SyntaxError

  def g():
      x: int  # Also a SyntaxError
      global x

原因就是這些變數并不歸屬于 globalnonlocal,因此型別注解歸屬于擁有變數的作用域,

只允許存在一個賦值物件和一個右值,此外,不能對 forwith 陳述句中用到的變數進行注解,可以像元組解包那樣提前做出注解:

  a: int
  for a in my_iter:
      ...

  f: MyFile
  with myfunc() as f:
      ...

存根檔案中的變數注解(Variable annotations in stub files)


因為變數注解的可讀性比型別注釋更好,所以推薦所有版本 Python(包括 Python 2.7)的存根檔案使用,請注意,Python 解釋器不會執行存根檔案,因此變數注解不會引發報錯,型別檢查程式應當支持所有版本 Python 存根檔案中的變數注解,例如:

  # file lib.pyi

  ADDRESS: unicode = ...

  class Error:
      cause: Union[str, unicode]

變數注解的推薦編碼風格(Preferred coding style for variable annotations)


對于模塊級變數、類與實體變數、區域變數,型別注解的冒號后面應帶一個空格,冒號前則不應有空格,如果賦值有右值,則等號兩邊都應帶有一個空格,例如:

- Yes::

    code: int

    class Point:
        coords: Tuple[int, int]
        label: str = '<unknown>'

- No::

    code:int  # No space after colon
    code : int  # Space before colon

    class Test:
        result: int=0  # No spaces around equality sign

標準庫和檔案的改動(Changes to Standard Library and Documentation)


  • typing 中已新加入一個協變型別 ClassVar[T_co],它只接受一個引數,應為一個合法的型別,它應用于不允許在類實體中賦值的類變數,這一約束由靜態檢查程式來保證,而不是運行時,有關 ClassVar 用法的示例和說明,請參閱類和實體變數的注解部分;有關實施 ClassVar 背后原因的更多資訊,請參見被拒絕/擱置的提案部分,

  • typing 模塊中的函式 get_type_hints 將會作出擴展,以便在運行時可由模塊、類和函式中讀取型別注解,注解以字典映射的形式回傳,由變數或引數映射為型別提示,若有向前參考則會先決議求值(evaluate),如果是類,則按方法的決議順序回傳由注解構造的映射(或許是個 collections.ChainMap),

  • 檔案中將會加入注解的推薦使用指南,包括本 PEP 和 PEP 484 所介紹規范的內容摘要,此外,還將發布一款將型別注釋轉換為型別注解的助手代碼,其將與標準庫分開發布,

型別注解的運行時效果(Runtime Effects of Type Annotations)


即便某本地變數從未賦值,只要對其添加了注解,解釋器就將視其為本地變數,本地變數的注解不會被決議求值,

  def f():
      x: NonexistentName  # No error.

但如果變數是模塊或類級別的,則型別注解被決議求值,

  x: NonexistentName  # Error!
  class X:
      var: NonexistentName  # Error!

此外在模塊或類級別,如果被注解物件是簡單名稱,則將其和注解一起存放于模塊或類的 __annotations__ 屬性中,若為私有變數則資訊會不全(mangle),形式為名稱和已決議注釋的有序字典,示例如下,

  from typing import Dict
  class Player:
      ...
  players: Dict[str, Player]
  __points: int

  print(__annotations__)
  # prints: {'players': typing.Dict[str, __main__.Player],
  #          '_Player__points': <class 'int'>}

__annotations__ 是可寫入屬性,因此以下操作是允許執行的:

  __annotations__['s'] = str

但如果試圖將 __annotations__ 修改為有序映射之外的其他物件,則可能會引發 TypeError:

  class C:
      __annotations__ = 42
      x: int = 5  # raises TypeError

注意:給 __annotations__ 賦值是 Python 解釋器允許的操作,它不會過問,但隨后的型別注解應該是 MutableMapping 型別,于是才會失敗,

在運行時讀取注解的推薦方式是采用 typing.get_type_hints 函式,與所有雙下劃線(dunder)屬性一樣,任何未在檔案注明的對 __annotations__ 的使用都難免失敗,且不會發出警告:

  from typing import Dict, ClassVar, get_type_hints
  class Starship:
      hitpoints: int = 50
      stats: ClassVar[Dict[str, int]] = {}
      shield: int = 100
      captain: str
      def __init__(self, captain: str) -> None:
          ...

  assert get_type_hints(Starship) == {'hitpoints': int,
                                      'stats': ClassVar[Dict[str, int]],
                                      'shield': int,
                                      'captain': str}

  assert get_type_hints(Starship.__init__) == {'captain': str,
                                               'return': None}

請注意,如果靜態檢查沒有找到注解資訊,則 __annotations__ 字典根本不會被創建,而且本地存盤注解獲得的好處,并不能抵消每次函式呼叫時都得創建并填充注解字典的開銷,因此,對函式級別的注解不會作決議求值和存盤,

注解的其他用途(Other uses of annotations)


因為 Python 并不在意型別注解的存在,而不是“未經加載即作決議求值”,所以支持本 PEP 的 Python 不會拒絕以下形式:

  alice: 'well done' = 'A+'
  bob: 'what a shame' = 'F-'

除非用 # type: ignore@no_type_check 進行了禁用,否則型別檢查程式在讀到注解時就會做出標記,

但正因為 Python 不在乎什么“型別”,所以如果以上代碼段是全域級別或位于某個類中,則__annotations__ 將會包含 {'alice': 'well done', 'bob': 'what a shame'}

這些存盤下來的注解可用作其他用途,但本 PEP 明確推薦將型別提示作為注解的首選用途,

被拒絕/擱置的提案(Rejected/Postponed Proposals)


  • 是否該引入變數注解?
    變數注解已經以型別注釋(comment)的形式存在了將近兩年,PEP 484 也已認可,在第三方型別檢查程式(mypy、pytype、PyCharm等)和運用型別檢查程式的專案中,注解已得以廣泛應用,但是注釋語法存在著很多缺點,這在原由部分已有列出,本 PEP 并不討論型別注解的必要性,而是介紹這種注解的語法,

  • 引入新的關鍵字:
    首先,要選出好的關鍵字非常困難,比如不能為 var,因為這在變數名中太常見了,如果要用于類變數或全域變數,則也不能為 local,其次,無論選擇什么,仍需要用到 __future__匯入陳述句,

  • def 作為關鍵字:
    這種提案可能如下所示:

    def primes: List[int] = []
    def captain: str

這里的問題是,對于幾代 Python 程式員(和工具!)而言,def 都表示“定義一個函式”,用它同時定義變數并不會增加清晰度,(盡管這確實是主觀意見,)

  • 用語法表明函式的用意:
    此條提案建議用 var = cast(annotation[, value]) 注釋變數型別,盡管這種語法緩解了型別注釋的某些問題(如 AST 中沒有注解),但其他問題還是沒有解決(如高可讀性、可能引入運行時開銷),

  • 元組解包格式中允許加入型別注解:
    這會導致歧義,以下陳述句的含義就不明:

    x, y: T

xy 都是 T 型別?或者 T 是由 xy 得來的元組型別?或者 x 的型別為 Anyy 的型別為 T?(如果出現在函式簽名中,則就是這個意思,)至少到目前為止禁止如此,不能讓人去猜,

  • 注解采用括號形式 (var: type)
    這是為解決上述歧義而在 python-ideas 上提出的,但語法啰嗦、好處不多且可讀性差,因此被拒絕,

  • 在連續賦值陳述句中允許使用注解:
    與元組解包格式類似,這存在歧義和可讀性問題,比如:

    x: int = y = 1
    z = w: int = 1

這里就存在歧義,yz 應該是什么型別呢?而且第二行還難以作語法決議,

  • with for 陳述句中允許使用注解:
    因為這樣在 for 陳述句中會讓真正的迭代程序難以被發現,而在 with 陳述句中則會引起 CPython 的 LL(1) 語法分析程式發生混亂,

  • 在函式定義階段對本地注解進行決議估值:
    Guido 已拒絕此提案,因為注解的位置強烈表明其位于周圍代碼的相同作用域內,

  • 在函式作用域記憶體儲變數注解:
    注解可本地訪問的收益不足以顯著抵消每次函式呼叫時創建和填充字典的開銷,

  • 對帶有注解的變數未經賦值即進行初始化
    有人在 python-ideas 上建議,將 x: int 中的 x 初始化為 None 或其他特殊常量(類似 Javascript 的 undefined),但是,在語言中新增一個單例值需要代碼處處做出判斷,因此,Guido 干脆地予以拒絕,

  • 在 typing 模塊中也加入 InstanceVar
    純屬多余,因為實體變數比類變數更為常用,常用用法理應默認,

  • 僅允許在方法內對實體變數進行注解:
    問題在于,除了初始化實體變數之外,許多 __init__ 方法還會干很多活兒,而且人眼很難找齊所有實體變數的注釋,有時 __init__ 會分解為更多助手方法,因此注釋就更加難以追蹤了,將實體變數的注釋放到類中,找起來可以更加輕松,也會給第一次閱讀代碼的人帶來便利,

  • 型別變數的注釋采用 x: class t = v 的語法:
    這樣會要求語法決議器變得更為復雜,class 關鍵字也會把簡單的語法高亮顯示程式弄糊涂,無論如何,都需要 ClassVar 把類變數存盤到 __annotations__ 中去,因此就選用了更簡單的語法,

  • 完全不用 ClassVar
    mypy 無法區分類變數和實體變數,可貌似也能混的不錯,因此才會有這個提案,但是型別檢查程式利用這些附加資訊能夠干很多有用的作業,比如標記出由實體對類變數的意外賦值,這種賦值會創建實體變數,將類變數遮掩起來(shadow),型別檢查程式還可以將實體變數標記為默認可修改,宣告眾所周知的風險,

  • ClassAttr 替換 ClassVar
    ClassVar 更為合適,主要是因為類的屬性可以有很多,如方法、描述符等,但是從概念上講,只有特定的屬性才是類變數(或常量),

  • 不對注解進行決議求值,只視其為字串:
    對函式注解始終都會進行決議求值,這樣就會與其表現不一,盡管未來可能會重新考慮,但在 PEP 484 中已決定應該將其作為單獨的 PEP 進行規范,

  • 在類的檔案字串中對變數型別進行注解
    許多專案已經應用了各種檔案字串規范,一致性往往不太好,通常還不符合 PEP 484 的注解語法,并且也還是需要比較復雜的特殊語法決議器,本 PEP 的目標正是要與第三方型別檢查工具協作,如此目標就會落空,

  • __annotations__ 實作為描述符
    這條提案是為了禁止將 __annotations__ 設為除字典和 None 之外的東西,Guido 拒絕了這個提案,認為沒有必要,如果試圖將 __annotations__ 修改為字典映射之外的任何東西,都會引發 TypeError,

  • 將純注解視同全域或非區域的:
    這條提案希望,出現在函式體內的無賦值注解不應進行任何決議求值,與之相反,本 PEP 表明,如果注解目標比單個名稱復雜,則應在函式體內的目標出現位置對其“左值部分”進行決議求值,以強制確認其是否已經定義,例如在以下示例中:

    def foo(self):
        slef.name: str

slef 就應該被決議求值,這樣若是其尚未定義(本例中貌似就是如此:-)),運行時將會引發錯誤,這樣就與帶初值時的表現更為一致,因此應該能減少意外情況的發生,還有一點請注意,如果注解目標是 self.name(這次拼寫正確了:-)),那么做過優化的編譯器并不保證會對 self 進行決議求值,只要能夠證明其一定是已定義的即可,

向下兼容性(Backwards Compatibility)


本 PEP 完全向下兼容,

實作代碼(Implementation)


適用于 Python 3.6 的已實作代碼可在以下 GitHub repo 中找到:https://github.com/ilevkivskyi/cpython/tree/pep-526,

著作權(Copyright)


本文已在公共領域發布,

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

標籤:Python

上一篇:Python3標準庫:shutil高層檔案操作

下一篇:在python檔案中操作django orm提示環境變數設定問題

標籤雲
其他(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