--- slideOptions: spotlight: enabled: false --- # Coding Convention > [time=Thu, Nov 4] > [name=Brian Chou] [name=yaya] [name=nick] [name=andy] [color=#e56e2d] --- ## Python 自動格式化工具 - linter:在程式未執行情況下檢查**程式語法正確性**的工具 ex: pylint - formatter:自動修正排版問題的工具 ex: yapf ---- ## pylint ![](https://i.imgur.com/kSeOvfP.png) ![](https://i.imgur.com/WsOyhsp.png) ---- ## Global variables - Avoid Global variables ```python= _MAX_HOLY_HANDGRENADE_COUNT = 3 ``` --- ## Comprehensions - 複雜的表達式可能難以閱讀 ---- ### no ```python= result = [complicated_transform( x, some_argument=x+1) for x in iterable if predicate(x)] ``` ### yes ```python= result = [complicated_transform(x) for x in iterable if predicate(x)] ``` ---- ### no ```python=! result = [(x, y) for x in range(10) for y in range(5) if x * y > 10] ``` ### yes ```python= result = [] for x in range(10): for y in range(5): if x * y > 10: result.append((x, y)) ``` --- ## lambda - 函數功能很小,可以使用 lambda來快速完成 function - 條件表達簡單時可用,__複雜則盡量避免__ ```python= add = lambda a, b: a+b a = 10 b = 20 c = add(a, b) print(c) ``` --- ## Default Argument - function’s parameter要有 Default Argument - Default Argument 只會被決定一次,必須特別注意傳入的參數是否為 mutable<!-- 因為 Python沒有 overloading: 當定義了多個同名函數時,後面的函數會覆蓋前面的函數 --> - 不要使用可變對像作為默認值 ---- ### Example ```python= No: def foo(a, b=time.time()): ... Yes: def foo(a, b=None): if b is None: b = [] ``` --- ## True/False Evaluations - 盡量使用隱含False意思(在Python中會被判定為False)的值,像是`0, None, [], {}, ''` - 處理整數時,直接與0比較可以避免一些問題 ---- ```python= if not users: print('no users') if i % 10 == 0: self.handle_multiple_of_ten() def f(x=None): if x is None: x = [] ``` --- ## Lexical Scoping - Lexical Scoping 代表著區塊間的包裹關係,被包裹在內層的區塊可以保護自己的變數不被外層取用,相反的外層區塊的變數還是可以被內層區塊使用 - Python中的這個特性可以使用 - 但只能讀取外層的變數,不能賦值。賦值會讓對外層變數的參考變成對區域變數的參考 ---- ```python= i = 4 def foo(x: Iterable[int]): def bar(): print(i, end='') # ... # A bunch of code here # ... for i in x: # Ah, i *is* local to foo, so this is what bar sees print(i, end='') bar() ``` So `foo([1, 2, 3])` will print `1 2 3 3`, not `1 2 3 4`. --- ## Function and Method Decorators - 只在有明顯優點時使用Decorator - 避免staticmethod(使用模組級別的Function替代),只在一些情況使用classmethod --- ## Threading - 不要依賴Python內建的原子操作 - 線程間溝通使用queue或lock --- ## Power Features - 不要使用Python裡一些太花俏的功能 --- ## Type Annotated Code - 建議加上Type Hint - 可以使用其他檢查工具如pytype --- ## Python Style Rules --- ## Semicolons ; ## Line length characters ---- - Maximum 80 ```python= # 括號 foo_bar(self, width, height, color='black', design=None, x='foo', emphasis=None, highlight=0) # 文字字串不符合單行 x = ('This will build a very long long ' 'long long long long long long string') #with with very_long_first_expression_function() as spam: with very_long_second_expression_function() as beans: place_order(beans, spam) ``` --- ## Parentheses() tuples - return statements - conditional statements --- ## Indentation 用空格取代tab ```python= #spaces foo = long_function_name(var_one, var_two, var_three, var_four) # 6 tabs foo = long_function_name(var_one, var_two, var_three, var_four) ``` ### commas ```python= golomb4 = [ 0, 1, 4, 6, ] ``` ---- ### Blank Lines Two blank lines between top-level definitions, be they function or class definitions. ---- ### Whitespace ```python= # spaces # yes spam(ham[1], {'eggs': 2}, []) # no spam( ham[ 1 ], { 'eggs' : 2 }, [ ] ) #binary operators # yes x == 1 # no x==1 # comments #yes foo = 1000 # comment long_name = 2 # comment that should not be aligned #no foo = 1000 # comment long_name = 2 # comment that should not be aligned ``` --- ### Comments > **我們決定用中文:D** - Args - Returns(or Yields: for generators) - Raises ```python= def fetch_smalltable_rows(table_handle: smalltable.Table, keys: Sequence[Union[bytes, str]], require_all_keys: bool = False, ) -> Mapping[bytes, tuple[str, ...]]: ``` --- ![](https://i.imgur.com/TS0oLKA.png) ---- - class -- public ![](https://i.imgur.com/YTcX1Sd.png) --- ### Strings - f-string, the % operator, or the format ```python= x = f'name: {name}; score: {n}' ``` - Avoid using the + and += operators ```python= x = 'name: ' + name + '; score: ' + str(n) ``` - 引用 ```python= Python('Why are you hiding your eyes?') Gollum("I'm scared of lint errors.") ``` ---- ### Error Messages ```python= if not 0 <= p <= 1: raise ValueError(f'Not a probability: {p!r}') try: os.rmdir(workdir) except OSError as error: # Interpolated pieces logging.warning('Could not remove directory (reason: %r): %r',error, workdir) ``` --- ### TODO - bug reference - yourusername [name=yaya] [name=brian] [name=nick] [name=andy] ```python=! # TODO(crbug.com/192795): Investigate cpufreq optimizations. # TODO(yourusername): File an issue and use a '*' for repetition. ``` --- ## import - 不要將 `import` 寫在同一行 - 依照字典序排序 import ```python= import sys import tensorflow as tf from otherproject.ai import mind ``` --- ## Statement - only one statement per line - 除非只有單行`if`敘述,且沒有`elif` --- ## Getters and Setters - 除非讀取/寫入變數時需要複雜的操作,否則簡單的讀寫變數應避免用Getters/Setters,而是直接將變數設為 public --- ## Naming - 命名應使用描述性的文字 - 禁止縮寫 - package/module name 禁止包含 `-` - 避免不必要的描述 i.e. `id_to_name_dict` - `CapWords` for class names. - `lower_with_under.py` for module names. ---- ![](https://i.imgur.com/ucRwUYe.png) --- ## Function - 函數長度不應超過40行 - 如果超過則儘可能切割成更多更小的功能 --- ## 縮排 ```python= def my_method( self, other_arg: Optional[MyLongType], ) -> tuple[MyLongType1, MyLongType1]: ``` - 函數參數過長時,一行一參數 - 為了讓最後的return可以換行,在最後一個參數加上逗號是可以的 ---- ```python= def my_function( long_variable_name: long_module_name.LongTypeName, ) -> None: ``` - 函數參數一行還是放不下時,切斷的地方應再向內縮排 --- ## 循環引用(Circular Dependencies) 定義:兩個檔案互相 import 對方 - 雖然可用一些方法繞過錯誤,但盡量避免 --- ## Typing 如果區域變數的型別難以辨識,可以加上 variable annotations ---- ### example: ```python= a: Foo = SomeUndecoratedFunction() ``` :::warning 冒號右邊要空白,左邊不需要 ::: ---- :::warning 舊的語法,勿用 ```python= a = SomeUndecoratedFunction() # type: Foo ``` ::: --- ### TypeVars 是個好東西,可以的話多多使用 ```python= from typing import TypeVar _T = TypeVar("_T") ... def next(l: list[_T]) -> _T: return l.pop() ``` ```python= AddableType = TypeVar("AddableType", int, float, str) def add(a: AddableType, b: AddableType) -> AddableType: return a + b ``` --- ## 臨別贈言(? - 始終保持一致 **BE CONSISTENT.** - 在開始 coding 之前先看看他周圍的 codes,永遠和周圍使用一樣的風格 --- # Roles & Responsibilities ---- ## 工作: - 討論、評估規格、改進 - 討論實作方式 - 寫程式,嘗試解決各種技術困難、與時俱進 - 錯誤追蹤和回報 - 撰寫註解 - 設計系統架構 - 與前端協作 - 不停學習 ---- ## 能力: - 基本的伺服器指令、網路知識、資料庫操作 / SQL、API 串接 - 暸解 security, authentication等議題 - 耐心與堅持 - 邏輯思考 ---- ## 價值與挑戰: - 確保資料正確性 - 系統穩定性 - 程式的彈性 --- # end~~
{"metaMigratedAt":"2023-06-17T13:27:13.193Z","metaMigratedFrom":"YAML","title":"Coding Convention","breaks":true,"contributors":"[{\"id\":\"c6f70f44-39e6-4fbc-b317-5e503cc1858e\",\"add\":9,\"del\":0},{\"id\":\"dacf2091-9992-4f5d-a557-c499f1dd5d55\",\"add\":3958,\"del\":1049},{\"id\":\"dbd3c3f6-7099-483f-b85b-2d0c22ec4ddb\",\"add\":2775,\"del\":779},{\"id\":\"ab1b9a7e-f184-4486-a8d4-a4431acd03d2\",\"add\":1746,\"del\":748},{\"id\":\"ff25936e-3d12-40ca-9fd0-f1fc893ea090\",\"add\":1079,\"del\":56}]"}
    203 views
   Owned this note