4. ਕੰਟਰੋਲ ਫਲੋ ਲਈ ਹੋਰ ਸਾਧਨ

ਹੁਣੇ ਜਾਣ-ਪਛਾਣ ਕਰਵਾਏ ਗਏ while statement ਤੋਂ ਇਲਾਵਾ, Python ਕੁਝ ਹੋਰ statements ਵੀ ਵਰਤਦਾ ਹੈ ਜਿਨ੍ਹਾਂ ਨਾਲ ਅਸੀਂ ਇਸ ਅਧਿਆਇ ਵਿੱਚ ਜਾਣੂ ਹੋਵਾਂਗੇ।

4.1. if ਸਟੇਟਮੈਂਟਾਂ

ਸ਼ਾਇਦ ਸਭ ਤੋਂ ਵੱਧ ਜਾਣਿਆ ਜਾਣ ਵਾਲਾ statement ਪ੍ਰਕਾਰ if statement ਹੈ। ਉਦਾਹਰਨ ਲਈ:

>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
...     x = 0
...     print('Negative changed to zero')
... elif x == 0:
...     print('Zero')
... elif x == 1:
...     print('Single')
... else:
...     print('More')
...
More

ਇੱਥੇ ਸ਼ੂਨ੍ਯ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ elif ਭਾਗ ਹੋ ਸਕਦੇ ਹਨ ਅਤੇ else ਭਾਗ ਵਿਕਲਪਿਕ ਹੈ। 'elif' keyword, 'else if' ਦਾ ਸੰਖੇਪ ਰੂਪ ਹੈ ਅਤੇ ਬਹੁਤ ਜ਼ਿਆਦਾ indentation ਤੋਂ ਬਚਣ ਲਈ ਲਾਭਦਾਇਕ ਹੈ। if ... elif ... elif ... ਦੀ ਲੜੀ ਹੋਰ ਭਾਸ਼ਾਵਾਂ ਵਿੱਚ ਮਿਲਣ ਵਾਲੇ switch ਜਾਂ case statements ਦਾ ਵਿਕਲਪ ਹੈ।

ਜੇ ਤੁਸੀਂ ਇੱਕੋ ਮੁੱਲ ਦੀ ਤੁਲਨਾ ਕਈ constants ਨਾਲ ਕਰ ਰਹੇ ਹੋ ਜਾਂ ਖਾਸ ਕਿਸਮਾਂ ਜਾਂ attributes ਦੀ ਜਾਂਚ ਕਰ ਰਹੇ ਹੋ, ਤਾਂ match statement ਵੀ ਤੁਹਾਡੇ ਲਈ ਲਾਭਦਾਇਕ ਹੋ ਸਕਦਾ ਹੈ। ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ match Statements ਵੇਖੋ।

4.2. for ਸਟੇਟਮੈਂਟਾਂ

Python ਵਿੱਚ ` for ` ਬਿਆਨ C ਜਾਂ Pascal ਵਿੱਚ ਤੁਸੀਂ ਜੋ ਵਰਤਦੇ ਹੋ, ਉਸ ਤੋਂ ਥੋੜ੍ਹਾ ਵੱਖਰਾ ਹੈ। ਸਦਾ ਗਿਣਤੀਆਂ ਦੀ ਗਣਿਤਕ ਕ੍ਰਮਵਾਰ (ਜਿਵੇਂ ਪਾਸਕਲ ਵਿੱਚ) 'ਤੇ ਦੁਹਰਾਉਣ ਦੀ ਬਜਾਏ, ਜਾਂ ਉਪਭੋਗਤਾ ਨੂੰ ਦੁਹਰਾਉਣ ਕਦਮ ਅਤੇ ਰੋਕਣ ਦੀ ਸ਼ਰਤ ਦੋਹਾਂ ਨਿਰਧਾਰਤ ਕਰਨ ਦੀ ਆਜ਼ਾਦੀ ਦੇਣ ਦੀ ਬਜਾਏ (ਜਿਵੇਂ C ਵਿੱਚ), Python ਦਾ for ਬਿਆਨ ਕਿਸੇ ਵੀ ਕ੍ਰਮ (ਸੂਚੀ ਜਾਂ ਸਤਰ) ਦੀਆਂ ਆਈਟਮਾਂ 'ਤੇ, ਉਹਨਾਂ ਦੇ ਕ੍ਰਮ ਵਿੱਚ, ਦੁਹਰਾਉਂਦਾ ਹੈ। ਉਦਾਹਰਨ ਵਜੋਂ (ਇਹ ਕੋਈ ਸ਼ਬਦ-ਚਿੱਤਰ ਨਹੀਂ ਹੈ):

>>> # Measure some strings:
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words:
...     print(w, len(w))
...
cat 3
window 6
defenestrate 12

ਉਸੇ collection ਉੱਤੇ iterate ਕਰਦੇ ਸਮੇਂ ਉਸਨੂੰ ਸੋਧਣ ਵਾਲਾ code ਸਹੀ ਤਰੀਕੇ ਨਾਲ ਲਿਖਣਾ ਮੁਸ਼ਕਲ ਹੋ ਸਕਦਾ ਹੈ। ਇਸਦੀ ਬਜਾਏ ਆਮ ਤੌਰ 'ਤੇ collection ਦੀ ਇੱਕ copy ਉੱਤੇ loop ਚਲਾਉਣਾ ਜਾਂ ਇੱਕ ਨਵੀਂ collection ਬਣਾਉਣਾ ਵਧੇਰੇ ਸੌਖਾ ਹੁੰਦਾ ਹੈ:

# Create a sample collection
users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

# Strategy:  Iterate over a copy
for user, status in users.copy().items():
    if status == 'inactive':
        del users[user]

# Strategy:  Create a new collection
active_users = {}
for user, status in users.items():
    if status == 'active':
        active_users[user] = status

4.3. range() ਫੰਕਸ਼ਨ

ਜੇ ਤੁਹਾਨੂੰ ਸੰਖਿਆਵਾਂ ਦੀ ਕਿਸੇ ਲੜੀ ਉੱਤੇ iterate ਕਰਨ ਦੀ ਲੋੜ ਹੋਵੇ, ਤਾਂ built-in function range() ਬਹੁਤ ਕੰਮ ਆਉਂਦਾ ਹੈ। ਇਹ arithmetic progressions ਤਿਆਰ ਕਰਦਾ ਹੈ:

>>> for i in range(5):
...     print(i)
...
0
1
2
3
4

ਦਿੱਤਾ ਗਿਆ ਅੰਤ ਬਿੰਦੂ ਕਦੇ ਵੀ ਤਿਆਰ ਕੀਤੀ ਗਈ ਕ੍ਰਮ ਦਾ ਹਿੱਸਾ ਨਹੀਂ ਹੁੰਦਾ; range(10) 10 ਮੁੱਲ ਤਿਆਰ ਕਰਦਾ ਹੈ, ਜੋ 10 ਲੰਬਾਈ ਵਾਲੀ ਕ੍ਰਮ ਦੀਆਂ ਆਈਟਮਾਂ ਲਈ ਵੈਧ ਸੂਚਕਾਂ ਹਨ। ਇਹ ਸੰਭਵ ਹੈ ਕਿ ਰੇਂਜ ਕਿਸੇ ਹੋਰ ਅੰਕ ਤੋਂ ਸ਼ੁਰੂ ਹੋਵੇ, ਜਾਂ ਵੱਖਰਾ ਵਾਧਾ (ਨਕਾਰਾਤਮਕ ਵੀ; ਕਈ ਵਾਰ ਇਸਨੂੰ 'ਸਟੈਪ' ਕਿਹਾ ਜਾਂਦਾ ਹੈ) ਨਿਰਧਾਰਤ ਕੀਤਾ ਜਾਵੇ:

>>> list(range(5, 10))
[5, 6, 7, 8, 9]

>>> list(range(0, 10, 3))
[0, 3, 6, 9]

>>> list(range(-10, -100, -30))
[-10, -40, -70]

ਕਿਸੇ sequence ਦੇ indices ਉੱਤੇ iterate ਕਰਨ ਲਈ ਤੁਸੀਂ range() ਅਤੇ len() ਨੂੰ ਇਸ ਤਰ੍ਹਾਂ ਇਕੱਠੇ ਵਰਤ ਸਕਦੇ ਹੋ:

>>> a = ['Mary', 'had', 'a', 'little', 'lamb']
>>> for i in range(len(a)):
...     print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb

ਹਾਲਾਂਕਿ ਜ਼ਿਆਦਾਤਰ ਅਜਿਹੇ ਮਾਮਲਿਆਂ ਵਿੱਚ enumerate() function ਦੀ ਵਰਤੋਂ ਕਰਨਾ ਵਧੇਰੇ ਸੁਵਿਧਾਜਨਕ ਹੁੰਦਾ ਹੈ। ਵੇਖੋ ਲੂਪਿੰਗ ਤਕਨੀਕਾਂ।

ਜੇ ਤੁਸੀਂ ਸਿਰਫ਼ ਇੱਕ range ਨੂੰ print ਕਰੋ ਤਾਂ ਇੱਕ ਦਿਲਚਸਪ ਗੱਲ ਹੁੰਦੀ ਹੈ:

>>> range(10)
range(0, 10)

range() ਦੁਆਰਾ ਵਾਪਸ ਕੀਤਾ ਗਿਆ object ਕਈ ਤਰੀਕਿਆਂ ਨਾਲ list ਵਾਂਗ ਵਿਹਾਰ ਕਰਦਾ ਹੈ, ਪਰ ਅਸਲ ਵਿੱਚ ਇਹ list ਨਹੀਂ ਹੁੰਦਾ। ਇਹ ਇੱਕ ਅਜਿਹਾ object ਹੈ ਜੋ iterate ਕਰਨ ਸਮੇਂ ਲੋੜੀਂਦੀ sequence ਦੇ items ਇੱਕ-ਇੱਕ ਕਰਕੇ ਵਾਪਸ ਕਰਦਾ ਹੈ, ਪਰ ਇਹ ਪੂਰੀ list ਨਹੀਂ ਬਣਾਉਂਦਾ, ਜਿਸ ਨਾਲ memory ਦੀ ਬਚਤ ਹੁੰਦੀ ਹੈ।

ਅਸੀਂ ਅਜਿਹੀ ਵਸਤੂ ਨੂੰ iterable ਕਹਿੰਦੇ ਹਾਂ, ਅਰਥਾਤ ਇਹ ਉਹਨਾਂ ਫੰਕਸ਼ਨਾਂ ਅਤੇ ਸੰਰਚਨਾਵਾਂ ਲਈ ਢੁਕਵੀਂ ਹੁੰਦੀ ਹੈ ਜੋ ਕਿਸੇ ਅਜਿਹੀ ਚੀਜ਼ ਦੀ ਉਮੀਦ ਕਰਦੀਆਂ ਹਨ ਜਿਸ ਤੋਂ ਉਹ ਲਗਾਤਾਰ ਤੱਤ ਪ੍ਰਾਪਤ ਕਰ ਸਕਣ, ਜਦੋਂ ਤੱਕ ਸਪਲਾਈ exhausted ਨਾ ਹੋ ਜਾਵੇ। ਅਸੀਂ ਦੇਖਿਆ ਹੈ ਕਿ for ਸਟੇਟਮੈਂਟ ਅਜਿਹੀ ਹੀ ਇੱਕ ਸੰਰਚਨਾ ਹੈ, ਜਦਕਿ ਕਿਸੇ iterable ਨੂੰ ਲੈਣ ਵਾਲੇ ਫੰਕਸ਼ਨ ਦੀ ਇੱਕ ਉਦਾਹਰਨ sum() ਹੈ:

>>> sum(range(4))  # 0 + 1 + 2 + 3
6

ਅੱਗੇ ਅਸੀਂ ਹੋਰ ਅਜੇਹੇ functions ਵੇਖਾਂਗੇ ਜੋ iterables ਵਾਪਸ ਕਰਦੇ ਹਨ ਅਤੇ iterables ਨੂੰ arguments ਵਜੋਂ ਸਵੀਕਾਰ ਕਰਦੇ ਹਨ। ਅਧਿਆਇ ਡਾਟਾ ਸੰਰਚਨਾਵਾਂ ਵਿੱਚ ਅਸੀਂ list() ਬਾਰੇ ਹੋਰ ਵਿਸਥਾਰ ਨਾਲ ਚਰਚਾ ਕਰਾਂਗੇ।

4.4. break ਅਤੇ continue Statements

break statement ਸਭ ਤੋਂ ਅੰਦਰਲੇ for ਜਾਂ while loop ਤੋਂ ਤੁਰੰਤ ਬਾਹਰ ਨਿਕਲ ਜਾਂਦੀ ਹੈ:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(f"{n} equals {x} * {n//x}")
...             break
...
4 equals 2 * 2
6 equals 2 * 3
8 equals 2 * 4
9 equals 3 * 3

continue statement loop ਦੀ ਅਗਲੀ iteration ਨਾਲ ਕਾਰਵਾਈ ਜਾਰੀ ਰੱਖਦੀ ਹੈ:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print(f"Found an even number {num}")
...         continue
...     print(f"Found an odd number {num}")
...
Found an even number 2
Found an odd number 3
Found an even number 4
Found an odd number 5
Found an even number 6
Found an odd number 7
Found an even number 8
Found an odd number 9

4.5. Loops ਉੱਤੇ else Clauses

for ਜਾਂ while loop ਵਿੱਚ break statement ਨੂੰ else clause ਨਾਲ ਜੋੜਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਜੇ loop break ਨੂੰ ਚਲਾਏ ਬਿਨਾਂ ਸਮਾਪਤ ਹੋ ਜਾਵੇ, ਤਾਂ else clause ਚਲਦਾ ਹੈ।

for loop ਵਿੱਚ else clause ਉਸ ਵੇਲੇ ਚਲਦਾ ਹੈ ਜਦੋਂ loop ਆਪਣੀ ਆਖਰੀ iteration ਪੂਰੀ ਕਰ ਲੈਂਦਾ ਹੈ, ਅਰਥਾਤ ਜੇ ਕੋਈ break ਨਾ ਆਇਆ ਹੋਵੇ।

while loop ਵਿੱਚ ਇਹ loop ਦੀ ਸ਼ਰਤ false ਹੋ ਜਾਣ ਤੋਂ ਬਾਅਦ ਚਲਦਾ ਹੈ।

ਦੋਵੇਂ ਕਿਸਮਾਂ ਦੇ loops ਵਿੱਚ, ਜੇ loop break ਨਾਲ ਸਮਾਪਤ ਕੀਤਾ ਗਿਆ ਹੋਵੇ ਤਾਂ else clause ਨਹੀਂ ਚਲਦਾ। ਇਸੇ ਤਰ੍ਹਾਂ, loop ਨੂੰ ਪਹਿਲਾਂ ਹੀ ਖਤਮ ਕਰਨ ਦੇ ਹੋਰ ਤਰੀਕੇ, ਜਿਵੇਂ return ਜਾਂ exception ਉੱਠਣਾ, ਵੀ else clause ਨੂੰ ਚਲਣ ਤੋਂ ਰੋਕਦੇ ਹਨ।

ਇਸਦੀ ਉਦਾਹਰਨ ਹੇਠਾਂ ਦਿੱਤੇ for ਲੂਪ ਵਿੱਚ ਵੇਖੀ ਜਾ ਸਕਦੀ ਹੈ, ਜੋ ਅਭਾਜ ਸੰਖਿਆਵਾਂ ਦੀ ਖੋਜ ਕਰਦਾ ਹੈ:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(ਹਾਂ, ਇਹ ਬਿਲਕੁਲ ਸਹੀ ਕੋਡ ਹੈ। ਧਿਆਨ ਨਾਲ ਵੇਖੋ: else clause for loop ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ, if statement ਨਾਲ ਨਹੀਂ।)

else ਕਲੌਜ਼ ਨੂੰ ਸੋਚਣ ਦਾ ਇੱਕ ਤਰੀਕਾ ਇਹ ਹੈ ਕਿ ਇਸਨੂੰ ਲੂਪ ਦੇ ਅੰਦਰ if ਨਾਲ ਜੋੜਿਆ ਹੋਇਆ ਸਮਝੋ। ਜਦੋਂ ਲੂਪ ਚਲਦਾ ਹੈ, ਇਹ if/if/if/else ਵਰਗੀ ਕ੍ਰਮਵਾਰ ਚਲਾਏਗਾ। loop ਦੇ ਅੰਦਰ if ਕਈ ਵਾਰੀ ਆਉਂਦਾ ਹੈ। ਜੇ ਇਹ ਸ਼ਰਤ ਕਦੇ ਵੀ ਸੱਚੀ ਹੋਵੇ, ਤਾਂ break ਚਲਦਾ ਹੈ। ਜੇ ਇਹ ਸ਼ਰਤ ਕਦੇ ਵੀ ਸੱਚੀ ਨਾ ਹੋਵੇ, ਤਾਂ loop ਦੇ ਬਾਹਰਲਾ else ਕਲੌਜ਼ ਚਲਦਾ ਹੈ।

ਜਦੋਂ ਲੂਪ ਨਾਲ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਇਹ try statement ਦੇ else clause ਨਾਲ ਵੱਧ ਮਿਲਦਾ ਹੈ, ਨਾ ਕਿ if statement ਦੇ else ਨਾਲ। try statement ਦਾ else ਉਸ ਵੇਲੇ ਚੱਲਦਾ ਹੈ ਜਦੋਂ ਕੋਈ exception ਨਹੀਂ ਆਉਂਦੀ, ਅਤੇ ਲੂਪ ਦਾ else ਉਸ ਵੇਲੇ ਚੱਲਦਾ ਹੈ ਜਦੋਂ ਕੋਈ break ਨਹੀਂ ਹੁੰਦਾ। try statement ਅਤੇ exceptions ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਅਪਵਾਦਾਂ ਨੂੰ ਸੰਭਾਲਣਾ ਵੇਖੋ।

4.6. pass Statements

pass statement ਕੋਈ ਕੰਮ ਨਹੀਂ ਕਰਦੀ। ਇਸਦੀ ਵਰਤੋਂ ਉਸ ਵੇਲੇ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਦੋਂ syntax ਅਨੁਸਾਰ ਕੋਈ statement ਲਾਜ਼ਮੀ ਹੋਵੇ ਪਰ program ਨੂੰ ਕੋਈ ਕਾਰਵਾਈ ਕਰਨ ਦੀ ਲੋੜ ਨਾ ਹੋਵੇ। ਉਦਾਹਰਨ ਲਈ:

>>> while True:
...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
...

ਇਸਦੀ ਵਰਤੋਂ ਆਮ ਤੌਰ 'ਤੇ ਘੱਟੋ-ਘੱਟ classes ਬਣਾਉਣ ਲਈ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:

>>> class MyEmptyClass:
...     pass
...

pass ਦੀ ਇੱਕ ਹੋਰ ਵਰਤੋਂ function ਜਾਂ conditional body ਲਈ placeholder ਵਜੋਂ ਹੈ ਜਦੋਂ ਤੁਸੀਂ ਨਵਾਂ code ਲਿਖ ਰਹੇ ਹੋ। ਇਹ ਤੁਹਾਨੂੰ ਹੋਰ ਅਮੂਰਤ ਪੱਧਰ 'ਤੇ ਸੋਚਦੇ ਰਹਿਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। pass ਨੂੰ ਚੁੱਪਚਾਪ ਅਣਡਿੱਠਾ ਕਰ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ:

>>> def initlog(*args):
...     pass   # Remember to implement this!
...

ਇਸ ਆਖਰੀ ਸਥਿਤੀ ਵਿੱਚ ਬਹੁਤ ਸਾਰੇ ਲੋਕ pass ਦੀ ਥਾਂ ellipsis literal ... ਵਰਤਦੇ ਹਨ। Python ਵਿੱਚ ਇਸਦਾ ਕੋਈ ਖਾਸ ਅਰਥ ਨਹੀਂ ਹੈ ਅਤੇ ਇਹ ਭਾਸ਼ਾ ਦੀ ਪਰਿਭਾਸ਼ਾ ਦਾ ਹਿੱਸਾ ਵੀ ਨਹੀਂ ਹੈ (ਤੁਸੀਂ ਇੱਥੇ ਕੋਈ ਵੀ constant expression ਵਰਤ ਸਕਦੇ ਹੋ), ਪਰ ਰਵਾਇਤੀ ਤੌਰ 'ਤੇ ... ਨੂੰ placeholder body ਵਜੋਂ ਵੀ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ। ਵੇਖੋ The Ellipsis Object।

4.7. match Statements

match ਬਿਆਨ ਇੱਕ ਐਕਸਪ੍ਰੈਸ਼ਨ ਲੈਂਦਾ ਹੈ ਅਤੇ ਇਸਦੀ ਕੀਮਤ ਨੂੰ ਇੱਕ ਜਾਂ ਵੱਧ ਕੇਸ ਬਲਾਕਾਂ ਵਿੱਚ ਦਿੱਤੇ ਗਏ ਲਗਾਤਾਰ ਪੈਟਰਨਾਂ ਨਾਲ ਤੁਲਨਾ ਕਰਦਾ ਹੈ। ਇਹ ਸਤਹੀ ਤੌਰ 'ਤੇ C, Java ਜਾਂ JavaScript (ਅਤੇ ਹੋਰ ਕਈ ਭਾਸ਼ਾਵਾਂ) ਵਿੱਚ switch ਬਿਆਨ ਵਰਗਾ ਲੱਗਦਾ ਹੈ, ਪਰ ਇਹ Rust ਜਾਂ Haskell ਵਰਗੀਆਂ ਭਾਸ਼ਾਵਾਂ ਵਿੱਚ pattern matching ਨਾਲ ਵੱਧ ਮਿਲਦਾ-ਜੁਲਦਾ ਹੈ। ਸਿਰਫ਼ ਉਹ ਪਹਿਲਾ ਪੈਟਰਨ ਜੋ ਮੇਲ ਖਾਂਦਾ ਹੈ, ਚਲਾਇਆ ਜਾਂਦਾ ਹੈ ਅਤੇ ਇਹ ਮੁੱਲ ਤੋਂ ਤੱਤ (ਕ੍ਰਮ ਦੇ ਐਲੀਮੈਂਟ ਜਾਂ ਆਬਜੈਕਟ ਦੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ) ਵੈਰੀਏਬਲਾਂ ਵਿੱਚ ਕੱਢ ਸਕਦਾ ਹੈ। ਜੇ ਕੋਈ ਕੇਸ ਮੇਲ ਨਹੀਂ ਖਾਂਦਾ, ਤਾਂ ਕੋਈ ਵੀ ਸ਼ਾਖਾ ਚਲਾਈ ਨਹੀਂ ਜਾਂਦੀ।

ਸਭ ਤੋਂ ਸਰਲ ਰੂਪ ਕਿਸੇ subject value ਦੀ ਤੁਲਨਾ ਇੱਕ ਜਾਂ ਵੱਧ literals ਨਾਲ ਕਰਦਾ ਹੈ:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

ਆਖਰੀ block ਉੱਤੇ ਧਿਆਨ ਦਿਓ: "variable name" _ ਇੱਕ wildcard ਵਜੋਂ ਕੰਮ ਕਰਦਾ ਹੈ ਅਤੇ ਹਮੇਸ਼ਾਂ match ਕਰ ਜਾਂਦਾ ਹੈ।

ਤੁਸੀਂ | ("or") ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਇੱਕ pattern ਵਿੱਚ ਕਈ literals ਨੂੰ ਜੋੜ ਸਕਦੇ ਹੋ:

case 401 | 403 | 404:
    return "Not allowed"

Patterns unpacking assignments ਵਰਗੇ ਦਿਸ ਸਕਦੇ ਹਨ ਅਤੇ variables ਨੂੰ bind ਕਰਨ ਲਈ ਵਰਤੇ ਜਾ ਸਕਦੇ ਹਨ:

# point ਇੱਕ (x, y) tuple ਹੈ
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")

ਇਸ ਉਦਾਹਰਨ ਨੂੰ ਧਿਆਨ ਨਾਲ ਸਮਝੋ! ਪਹਿਲੇ pattern ਵਿੱਚ ਦੋ literals ਹਨ ਅਤੇ ਇਸਨੂੰ ਉੱਪਰ ਦਿਖਾਏ literal pattern ਦੇ ਵਿਸਤਾਰ ਵਜੋਂ ਸਮਝਿਆ ਜਾ ਸਕਦਾ ਹੈ। ਅਗਲੇ ਦੋ patterns ਇੱਕ literal ਅਤੇ ਇੱਕ variable ਨੂੰ ਜੋੜਦੇ ਹਨ, ਅਤੇ variable subject (point) ਵਿੱਚੋਂ ਇੱਕ ਮੁੱਲ bind ਕਰਦਾ ਹੈ। ਚੌਥਾ pattern ਦੋ ਮੁੱਲਾਂ ਨੂੰ capture ਕਰਦਾ ਹੈ, ਜਿਸ ਕਾਰਨ ਇਹ ਧਾਰਣਾਤਮਕ ਤੌਰ 'ਤੇ unpacking assignment (x, y) = point ਵਰਗਾ ਹੈ।

ਜੇ ਤੁਸੀਂ ਆਪਣੇ data ਨੂੰ ਢਾਂਚਾਬੱਧ ਕਰਨ ਲਈ classes ਵਰਤ ਰਹੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ class name ਤੋਂ ਬਾਅਦ constructor ਵਰਗੀ argument list ਵਰਤ ਸਕਦੇ ਹੋ, ਜਿਸ ਵਿੱਚ attributes ਨੂੰ variables ਵਿੱਚ capture ਕਰਨ ਦੀ ਸਮਰੱਥਾ ਹੁੰਦੀ ਹੈ:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def where_is(point):
    match point:
        case Point(x=0, y=0):
            print("Origin")
        case Point(x=0, y=y):
            print(f"Y={y}")
        case Point(x=x, y=0):
            print(f"X={x}")
        case Point():
            print("Somewhere else")
        case _:
            print("Not a point")

ਤੁਸੀਂ ਕੁਝ builtin classes (ਜਿਵੇਂ dataclasses) ਨਾਲ positional parameters ਵਰਤ ਸਕਦੇ ਹੋ ਜੋ ਆਪਣੇ attributes ਲਈ ਕ੍ਰਮ ਨਿਰਧਾਰਤ ਕਰਦੀਆਂ ਹਨ। ਤੁਸੀਂ ਆਪਣੀਆਂ classes ਵਿੱਚ __match_args__ special attribute ਸੈੱਟ ਕਰਕੇ patterns ਵਿੱਚ attributes ਦੀ ਖਾਸ position ਵੀ ਨਿਰਧਾਰਤ ਕਰ ਸਕਦੇ ਹੋ। ਜੇ ਇਸਨੂੰ ("x", "y") ਸੈੱਟ ਕੀਤਾ ਜਾਵੇ, ਤਾਂ ਹੇਠਾਂ ਦਿੱਤੇ ਸਾਰੇ patterns ਇੱਕੋ ਜਿਹੇ ਹਨ (ਅਤੇ ਸਾਰੇ y attribute ਨੂੰ var variable ਨਾਲ bind ਕਰਦੇ ਹਨ):

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

ਪੈਟਰਨਾਂ ਨੂੰ ਪੜ੍ਹਨ ਦਾ ਇੱਕ ਸਿਫ਼ਾਰਸ਼ੀ ਤਰੀਕਾ ਇਹ ਹੈ ਕਿ ਉਨ੍ਹਾਂ ਨੂੰ ਉਸ ਚੀਜ਼ ਦੇ ਵਿਸਤ੍ਰਿਤ ਰੂਪ ਵਜੋਂ ਦੇਖਿਆ ਜਾਵੇ ਜੋ ਤੁਸੀਂ ਕਿਸੇ ਅਸਾਈਨਮੈਂਟ ਦੇ ਖੱਬੇ ਪਾਸੇ ਰੱਖਦੇ ਹੋ, ਤਾਂ ਜੋ ਇਹ ਸਮਝਿਆ ਜਾ ਸਕੇ ਕਿ ਕਿਹੜੇ ਵੇਰੀਏਬਲ ਕਿਸ ਮੁੱਲ ਨਾਲ ਸੈੱਟ ਕੀਤੇ ਜਾਣਗੇ। ਸਿਰਫ਼ ਸਟੈਂਡਅਲੋਨ ਨਾਮ (ਜਿਵੇਂ ਉਪਰ ਦਿੱਤਾ var ) ਮੈਚ ਸਟੇਟਮੈਂਟ ਦੁਆਰਾ ਅਸਾਈਨ ਕੀਤੇ ਜਾਂਦੇ ਹਨ। ਡੌਟਡ ਨਾਮ (ਜਿਵੇਂ foo.bar), ਐਟ੍ਰਿਬਿਊਟ ਨਾਮ (ਉਪਰ ਦਿੱਤੇ x= ਅਤੇ y= ) ਜਾਂ ਕਲਾਸ ਨਾਮ (ਜਿਨ੍ਹਾਂ ਦੇ ਨਾਲ "(...)" ਲਿਖਿਆ ਹੁੰਦਾ ਹੈ, ਜਿਵੇਂ ਉਪਰ ਦਿੱਤਾ Point ) ਕਦੇ ਵੀ ਅਸਾਈਨ ਨਹੀਂ ਕੀਤੇ ਜਾਂਦੇ।

Patterns ਨੂੰ ਮਨਚਾਹੇ ਢੰਗ ਨਾਲ nested ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਜੇ ਸਾਡੇ ਕੋਲ __match_args__ ਵਾਲੀ Points ਦੀ ਇੱਕ ਛੋਟੀ ਸੂਚੀ ਹੋਵੇ, ਤਾਂ ਅਸੀਂ ਇਸਨੂੰ ਇਸ ਤਰ੍ਹਾਂ match ਕਰ ਸਕਦੇ ਹਾਂ:

class Point:
    __match_args__ = ('x', 'y')
    def __init__(self, x, y):
        self.x = x
        self.y = y

match points:
    case []:
        print("No points")
    case [Point(0, 0)]:
        print("The origin")
    case [Point(x, y)]:
        print(f"Single point {x}, {y}")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two on the Y axis at {y1}, {y2}")
    case _:
        print("Something else")

ਅਸੀਂ ਕਿਸੇ pattern ਨਾਲ if clause ਜੋੜ ਸਕਦੇ ਹਾਂ, ਜਿਸਨੂੰ "guard" ਕਿਹਾ ਜਾਂਦਾ ਹੈ। ਜੇ guard false ਹੋਵੇ, ਤਾਂ match ਅਗਲੇ case block ਦੀ ਜਾਂਚ ਕਰਦਾ ਹੈ। ਧਿਆਨ ਦਿਓ ਕਿ value capture guard ਦੀ ਜਾਂਚ ਤੋਂ ਪਹਿਲਾਂ ਹੋ ਜਾਂਦੀ ਹੈ:

match point:
    case Point(x, y) if x == y:
        print(f"Y=X at {x}")
    case Point(x, y):
        print(f"Not on the diagonal")

ਇਸ statement ਦੀਆਂ ਕੁਝ ਹੋਰ ਮਹੱਤਵਪੂਰਨ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ:

  • Unpacking assignments ਦੀ ਤਰ੍ਹਾਂ, tuple ਅਤੇ list patterns ਦਾ ਅਰਥ ਵੀ ਇੱਕੋ ਜਿਹਾ ਹੁੰਦਾ ਹੈ ਅਤੇ ਇਹ ਮਨਚਾਹੀਆਂ sequences ਨਾਲ match ਕਰ ਸਕਦੇ ਹਨ। ਇੱਕ ਮਹੱਤਵਪੂਰਨ ਅਪਵਾਦ ਇਹ ਹੈ ਕਿ ਇਹ iterators ਜਾਂ strings ਨਾਲ match ਨਹੀਂ ਕਰਦੇ।

  • Sequence patterns extended unpacking ਦਾ ਸਮਰਥਨ ਕਰਦੇ ਹਨ: [x, y, *rest] ਅਤੇ (x, y, *rest) unpacking assignments ਵਾਂਗ ਕੰਮ ਕਰਦੇ ਹਨ। * ਤੋਂ ਬਾਅਦ ਆਉਣ ਵਾਲਾ ਨਾਮ _ ਵੀ ਹੋ ਸਕਦਾ ਹੈ, ਇਸ ਲਈ (x, y, *_) ਘੱਟੋ-ਘੱਟ ਦੋ items ਵਾਲੀ sequence ਨਾਲ match ਕਰਦਾ ਹੈ ਬਿਨਾਂ ਬਾਕੀ items ਨੂੰ bind ਕੀਤੇ।

  • Mapping patterns: {"bandwidth": b, "latency": l} dictionary ਵਿੱਚੋਂ "bandwidth" ਅਤੇ "latency" ਦੇ ਮੁੱਲ capture ਕਰਦੇ ਹਨ। Sequence patterns ਦੇ ਉਲਟ, ਵਾਧੂ keys ਨੂੰ ਅਣਡਿੱਠਾ ਕਰ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ। **rest ਵਰਗੀ unpacking ਦਾ ਵੀ ਸਮਰਥਨ ਹੈ। (ਪਰ **_ ਬੇਲੋੜਾ ਹੋਵੇਗਾ, ਇਸ ਲਈ ਇਸਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ।)

  • Subpatterns ਨੂੰ as keyword ਦੀ ਵਰਤੋਂ ਨਾਲ capture ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ:

    case (Point(x1, y1), Point(x2, y2) as p2): ...
    

    ਇਹ input ਦੇ ਦੂਜੇ element ਨੂੰ p2 ਵਜੋਂ capture ਕਰੇਗਾ (ਜਦੋਂ ਤੱਕ input ਦੋ points ਵਾਲੀ sequence ਹੈ)।

  • ਜ਼ਿਆਦਾਤਰ literals ਦੀ ਤੁਲਨਾ equality ਦੇ ਆਧਾਰ 'ਤੇ ਕੀਤੀ ਜਾਂਦੀ ਹੈ, ਪਰ singletons True, False ਅਤੇ None ਦੀ ਤੁਲਨਾ identity ਦੇ ਆਧਾਰ 'ਤੇ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।

  • Patterns named constants ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹਨ। ਇਹ dotted names ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ ਤਾਂ ਜੋ ਇਨ੍ਹਾਂ ਨੂੰ capture variables ਵਜੋਂ ਨਾ ਸਮਝਿਆ ਜਾਵੇ:

    from enum import Enum
    class Color(Enum):
        RED = 'red'
        GREEN = 'green'
        BLUE = 'blue'
    
    color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))
    
    match color:
        case Color.RED:
            print("I see red!")
        case Color.GREEN:
            print("Grass is green")
        case Color.BLUE:
            print("I'm feeling the blues :(")
    

ਹੋਰ ਵਿਸਤ੍ਰਿਤ ਵਿਆਖਿਆ ਅਤੇ ਵਾਧੂ ਉਦਾਹਰਨਾਂ ਲਈ ਤੁਸੀਂ PEP 636 ਵੇਖ ਸਕਦੇ ਹੋ, ਜੋ tutorial ਰੂਪ ਵਿੱਚ ਲਿਖਿਆ ਗਿਆ ਹੈ।

4.8. Functions ਦੀ ਪਰਿਭਾਸ਼ਾ

ਅਸੀਂ ਇੱਕ function ਬਣਾ ਸਕਦੇ ਹਾਂ ਜੋ Fibonacci series ਨੂੰ ਕਿਸੇ ਮਨਚਾਹੀ ਸੀਮਾ ਤੱਕ ਲਿਖੇ:

>>> def fib(n):    # write Fibonacci series less than n
...     """Print a Fibonacci series less than n."""
...     a, b = 0, 1
...     while a < n:
...         print(a, end=' ')
...         a, b = b, a+b
...     print()
...
>>> # Now call the function we just defined:
>>> fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

def keyword ਇੱਕ function definition ਦੀ ਸ਼ੁਰੂਆਤ ਕਰਦਾ ਹੈ। ਇਸ ਤੋਂ ਬਾਅਦ function ਦਾ ਨਾਮ ਅਤੇ formal parameters ਦੀ parenthesized list ਆਉਣੀ ਚਾਹੀਦੀ ਹੈ। Function ਦਾ body ਬਣਾਉਣ ਵਾਲੀਆਂ statements ਅਗਲੀ ਲਾਈਨ ਤੋਂ ਸ਼ੁਰੂ ਹੁੰਦੀਆਂ ਹਨ ਅਤੇ ਉਹਨਾਂ ਦਾ indented ਹੋਣਾ ਲਾਜ਼ਮੀ ਹੈ।

Function body ਦੀ ਪਹਿਲੀ statement ਵਿਕਲਪਕ ਤੌਰ 'ਤੇ ਇੱਕ string literal ਹੋ ਸਕਦੀ ਹੈ; ਇਸ string literal ਨੂੰ function ਦੀ documentation string ਜਾਂ docstring ਕਿਹਾ ਜਾਂਦਾ ਹੈ। (ਡਾਕੂਮੈਂਟੇਸ਼ਨ ਸਟ੍ਰਿੰਗਾਂ ਵਿੱਚ docstrings ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ ਮਿਲੇਗੀ।) ਕਈ tools docstrings ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਆਪਣੇ ਆਪ online ਜਾਂ printed documentation ਤਿਆਰ ਕਰਦੇ ਹਨ ਜਾਂ ਵਰਤੋਂਕਾਰ ਨੂੰ code ਨੂੰ interactively ਵੇਖਣ ਦੀ ਸੁਵਿਧਾ ਦਿੰਦੇ ਹਨ। ਇਸ ਲਈ ਆਪਣੇ code ਵਿੱਚ docstrings ਸ਼ਾਮਲ ਕਰਨਾ ਇੱਕ ਵਧੀਆ ਅਭਿਆਸ ਹੈ।

ਕਿਸੇ function ਦੀ execution ਉਸਦੇ local variables ਲਈ ਇੱਕ ਨਵੀਂ symbol table ਬਣਾਉਂਦੀ ਹੈ। ਹੋਰ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ, function ਦੇ ਅੰਦਰ ਕੀਤੀਆਂ ਸਾਰੀਆਂ variable assignments local symbol table ਵਿੱਚ ਸੰਭਾਲੀਆਂ ਜਾਂਦੀਆਂ ਹਨ; ਜਦਕਿ variable references ਪਹਿਲਾਂ local symbol table, ਫਿਰ enclosing functions ਦੀਆਂ local symbol tables, ਫਿਰ global symbol table ਅਤੇ ਆਖ਼ਰ ਵਿੱਚ built-in names ਦੀ table ਵਿੱਚ ਖੋਜੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। ਇਸ ਲਈ global variables ਅਤੇ enclosing functions ਦੇ variables ਨੂੰ function ਦੇ ਅੰਦਰ ਸਿੱਧਾ ਮੁੱਲ ਨਹੀਂ ਦਿੱਤਾ ਜਾ ਸਕਦਾ (ਸਿਵਾਏ ਉਹਨਾਂ ਦੇ ਜੋ global ਜਾਂ nonlocal statement ਰਾਹੀਂ ਘੋਸ਼ਿਤ ਕੀਤੇ ਗਏ ਹੋਣ), ਹਾਲਾਂਕਿ ਉਨ੍ਹਾਂ ਨੂੰ reference ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।

ਜਦੋਂ ਕਿਸੇ function ਨੂੰ ਕਾਲ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਉਸਦੇ actual parameters (arguments) ਉਸ function ਦੀ local symbol table ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤੇ ਜਾਂਦੇ ਹਨ; ਇਸ ਤਰ੍ਹਾਂ arguments call by value ਰਾਹੀਂ ਪਾਸ ਕੀਤੇ ਜਾਂਦੇ ਹਨ (ਜਿੱਥੇ value ਅਸਲ ਵਿੱਚ object ਦਾ reference ਹੁੰਦਾ ਹੈ, object ਦਾ ਮੁੱਲ ਨਹੀਂ)। [1] ਜਦੋਂ ਕੋਈ function ਕਿਸੇ ਹੋਰ function ਨੂੰ ਜਾਂ ਆਪਣੇ ਆਪ ਨੂੰ recursively ਕਾਲ ਕਰਦਾ ਹੈ, ਤਾਂ ਉਸ ਕਾਲ ਲਈ ਇੱਕ ਨਵੀਂ local symbol table ਬਣਾਈ ਜਾਂਦੀ ਹੈ।

Function definition ਮੌਜੂਦਾ symbol table ਵਿੱਚ function name ਨੂੰ function object ਨਾਲ ਜੋੜਦੀ ਹੈ। Interpreter ਉਸ ਨਾਮ ਦੁਆਰਾ ਦਰਸਾਏ object ਨੂੰ user-defined function ਵਜੋਂ ਪਛਾਣਦਾ ਹੈ। ਹੋਰ ਨਾਮ ਵੀ ਉਸੇ function object ਵੱਲ ਇਸ਼ਾਰਾ ਕਰ ਸਕਦੇ ਹਨ ਅਤੇ function ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਲਈ ਵਰਤੇ ਜਾ ਸਕਦੇ ਹਨ:

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

ਜੇ ਤੁਸੀਂ ਹੋਰ ਭਾਸ਼ਾਵਾਂ ਤੋਂ ਆ ਰਹੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ ਕਹਿ ਸਕਦੇ ਹੋ ਕਿ fib ਇੱਕ function ਨਹੀਂ ਸਗੋਂ ਇੱਕ procedure ਹੈ ਕਿਉਂਕਿ ਇਹ ਕੋਈ ਮੁੱਲ ਵਾਪਸ ਨਹੀਂ ਕਰਦਾ। ਅਸਲ ਵਿੱਚ, ਉਹ functions ਵੀ ਜਿਨ੍ਹਾਂ ਵਿੱਚ return statement ਨਹੀਂ ਹੁੰਦੀ, ਇੱਕ ਮੁੱਲ ਵਾਪਸ ਕਰਦੇ ਹਨ, ਭਾਵੇਂ ਉਹ ਕਾਫ਼ੀ ਸਧਾਰਣ ਹੋਵੇ। ਇਸ ਮੁੱਲ ਨੂੰ None ਕਿਹਾ ਜਾਂਦਾ ਹੈ (ਇਹ ਇੱਕ built-in ਨਾਮ ਹੈ)। ਜੇ None ਹੀ ਇਕੱਲਾ ਲਿਖਿਆ ਜਾਣ ਵਾਲਾ ਮੁੱਲ ਹੋਵੇ, ਤਾਂ interpreter ਆਮ ਤੌਰ 'ਤੇ ਇਸਨੂੰ ਨਹੀਂ ਦਿਖਾਉਂਦਾ। ਜੇ ਤੁਸੀਂ ਇਸਨੂੰ ਦੇਖਣਾ ਚਾਹੋ ਤਾਂ print() ਦੀ ਵਰਤੋਂ ਕਰ ਸਕਦੇ ਹੋ:

>>> fib(0)
>>> print(fib(0))
None

Fibonacci ਲੜੀ ਦੀਆਂ ਸੰਖਿਆਵਾਂ ਨੂੰ print ਕਰਨ ਦੀ ਬਜਾਏ ਉਹਨਾਂ ਦੀ ਇੱਕ list ਵਾਪਸ ਕਰਨ ਵਾਲਾ function ਲਿਖਣਾ ਆਸਾਨ ਹੈ:

>>> def fib2(n):  # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

ਇਹ ਉਦਾਹਰਨ, ਹਮੇਸ਼ਾਂ ਦੀ ਤਰ੍ਹਾਂ, Python ਦੀਆਂ ਕੁਝ ਨਵੀਆਂ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਨੂੰ ਦਰਸਾਉਂਦੀ ਹੈ:

  • return statement ਕਿਸੇ function ਤੋਂ ਇੱਕ ਮੁੱਲ ਵਾਪਸ ਕਰਦੀ ਹੈ। expression argument ਤੋਂ ਬਿਨਾਂ return None ਵਾਪਸ ਕਰਦੀ ਹੈ। Function ਦੇ ਅੰਤ ਤੱਕ ਪਹੁੰਚ ਜਾਣ 'ਤੇ ਵੀ None ਹੀ ਵਾਪਸ ਹੁੰਦਾ ਹੈ।

  • Statement result.append(a) list object result ਦੀ ਇੱਕ method ਨੂੰ ਕਾਲ ਕਰਦੀ ਹੈ। Method ਉਹ function ਹੁੰਦੀ ਹੈ ਜੋ ਕਿਸੇ object ਨਾਲ ਸੰਬੰਧਿਤ ਹੁੰਦੀ ਹੈ ਅਤੇ ਜਿਸਦਾ ਨਾਮ obj.methodname ਦੇ ਰੂਪ ਵਿੱਚ ਹੁੰਦਾ ਹੈ, ਜਿੱਥੇ obj ਕੋਈ object ਹੁੰਦਾ ਹੈ (ਇਹ ਇੱਕ expression ਵੀ ਹੋ ਸਕਦਾ ਹੈ) ਅਤੇ methodname ਉਸ method ਦਾ ਨਾਮ ਹੁੰਦਾ ਹੈ ਜੋ object ਦੀ type ਦੁਆਰਾ ਪਰਿਭਾਸ਼ਿਤ ਕੀਤੀ ਗਈ ਹੋਵੇ। ਵੱਖ-ਵੱਖ types ਵੱਖ-ਵੱਖ methods ਪਰਿਭਾਸ਼ਿਤ ਕਰਦੀਆਂ ਹਨ। ਵੱਖਰੀਆਂ types ਦੀਆਂ methods ਦਾ ਨਾਮ ਇੱਕੋ ਜਿਹਾ ਹੋ ਸਕਦਾ ਹੈ ਬਿਨਾਂ ਕਿਸੇ ਗਲਤਫਹਮੀ ਦੇ। (classes ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਆਪਣੀਆਂ object types ਅਤੇ methods ਵੀ ਬਣਾਈਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ; ਵੇਖੋ ਕਲਾਸਾਂ)। ਉਦਾਹਰਨ ਵਿੱਚ ਦਿਖਾਈ ਗਈ append() method list objects ਲਈ ਪਰਿਭਾਸ਼ਿਤ ਹੈ; ਇਹ list ਦੇ ਅੰਤ ਵਿੱਚ ਇੱਕ ਨਵਾਂ element ਜੋੜਦੀ ਹੈ। ਇਸ ਉਦਾਹਰਨ ਵਿੱਚ ਇਹ result = result + [a] ਦੇ ਬਰਾਬਰ ਹੈ, ਪਰ ਹੋਰ ਪ੍ਰਭਾਵਸ਼ਾਲੀ ਹੈ।

4.9. ਫੰਕਸ਼ਨਾਂ ਦੀ ਪਰਿਭਾਸ਼ਾ ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ

ਫੰਕਸ਼ਨਾਂ ਨੂੰ ਬਦਲਦੀ ਗਿਣਤੀ ਵਾਲੇ arguments ਨਾਲ ਪਰਿਭਾਸ਼ਿਤ ਕਰਨਾ ਵੀ ਸੰਭਵ ਹੈ। ਇਸ ਦੀਆਂ ਤਿੰਨ ਰੂਪ-ਰੇਖਾਵਾਂ ਹਨ, ਜਿਨ੍ਹਾਂ ਨੂੰ ਇਕੱਠੇ ਵੀ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ।

4.9.1. ਡਿਫਾਲਟ ਆਰਗਿਊਮੈਂਟ ਮੁੱਲ

ਸਭ ਤੋਂ ਲਾਭਦਾਇਕ ਤਰੀਕਾ ਇੱਕ ਜਾਂ ਵੱਧ arguments ਲਈ ਡਿਫਾਲਟ ਮੁੱਲ ਨਿਰਧਾਰਤ ਕਰਨਾ ਹੈ। ਇਸ ਨਾਲ ਅਜਿਹਾ function ਬਣਦਾ ਹੈ ਜਿਸਨੂੰ ਉਸਦੀ ਪਰਿਭਾਸ਼ਾ ਵਿੱਚ ਮਨਜ਼ੂਰ ਕੀਤੇ ਗਏ arguments ਤੋਂ ਘੱਟ arguments ਨਾਲ ਵੀ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ:

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while True:
        reply = input(prompt)
        if reply in {'y', 'ye', 'yes'}:
            return True
        if reply in {'n', 'no', 'nop', 'nope'}:
            return False
        retries = retries - 1
        if retries < 0:
            raise ValueError('invalid user response')
        print(reminder)

ਇਸ function ਨੂੰ ਕਈ ਤਰੀਕਿਆਂ ਨਾਲ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ:

  • ਸਿਰਫ਼ ਲਾਜ਼ਮੀ argument ਦੇ ਕੇ: ask_ok('Do you really want to quit?')

  • ਵਿਕਲਪਿਕ arguments ਵਿੱਚੋਂ ਇੱਕ ਦੇ ਕੇ: ask_ok('OK to overwrite the file?', 2)

  • ਜਾਂ ਸਾਰੇ arguments ਦੇ ਕੇ: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')

ਇਹ ਉਦਾਹਰਨ in keyword ਨਾਲ ਵੀ ਜਾਣੂ ਕਰਵਾਉਂਦੀ ਹੈ। ਇਹ ਜਾਂਚਦੀ ਹੈ ਕਿ ਕਿਸੇ sequence ਵਿੱਚ ਕੋਈ ਖਾਸ ਮੁੱਲ ਮੌਜੂਦ ਹੈ ਜਾਂ ਨਹੀਂ।

ਡਿਫਾਲਟ ਮੁੱਲਾਂ ਦਾ ਮੁਲਾਂਕਣ function ਦੀ ਪਰਿਭਾਸ਼ਾ ਦੇ ਸਮੇਂ, defining scope ਵਿੱਚ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਇਸ ਲਈ

i = 5

def f(arg=i):
    print(arg)

i = 6
f()

ਇਹ 5 ਪ੍ਰਿੰਟ ਕਰੇਗਾ।

ਮਹੱਤਵਪੂਰਨ ਚੇਤਾਵਨੀ: ਡਿਫਾਲਟ ਮੁੱਲ ਦਾ ਮੁਲਾਂਕਣ ਸਿਰਫ਼ ਇੱਕ ਵਾਰ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਜਦੋਂ ਡਿਫਾਲਟ ਇੱਕ mutable object ਹੋਵੇ, ਜਿਵੇਂ list, dictionary ਜਾਂ ਬਹੁਤੀਆਂ classes ਦੇ instances, ਤਾਂ ਇਹ ਗੱਲ ਮਹੱਤਵਪੂਰਨ ਬਣ ਜਾਂਦੀ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਹੇਠਾਂ ਦਿੱਤਾ function ਆਪਣੀਆਂ ਅਗਲੀਆਂ ਕਾਲਾਂ ਵਿੱਚ ਪਾਸ ਕੀਤੇ arguments ਨੂੰ ਇਕੱਠਾ ਕਰਦਾ ਰਹਿੰਦਾ ਹੈ:

def f(a, L=[]):
    L.append(a)
    return L

print(f(1))
print(f(2))
print(f(3))

ਇਹ ਪ੍ਰਿੰਟ ਕਰੇਗਾ

[1]
[1, 2]
[1, 2, 3]

ਜੇ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ ਡਿਫਾਲਟ ਮੁੱਲ ਅਗਲੀਆਂ ਕਾਲਾਂ ਵਿੱਚ ਸਾਂਝਾ ਹੋਵੇ, ਤਾਂ function ਨੂੰ ਇਸ ਤਰ੍ਹਾਂ ਲਿਖ ਸਕਦੇ ਹੋ:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

4.9.2. ਕੀਵਰਡ ਆਰਗਿਊਮੈਂਟ

Functions ਨੂੰ kwarg=value ਦੇ ਰੂਪ ਵਾਲੇ keyword arguments ਦੀ ਵਰਤੋਂ ਕਰਕੇ ਵੀ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, ਹੇਠਾਂ ਦਿੱਤਾ function:

def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
    print("-- This parrot wouldn't", action, end=' ')
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It's", state, "!")

ਇਹ ਇੱਕ ਲਾਜ਼ਮੀ argument (voltage) ਅਤੇ ਤਿੰਨ ਵਿਕਲਪਿਕ arguments (state, action ਅਤੇ type) ਸਵੀਕਾਰ ਕਰਦਾ ਹੈ। ਇਸ function ਨੂੰ ਹੇਠਾਂ ਦਿੱਤੇ ਕਿਸੇ ਵੀ ਤਰੀਕੇ ਨਾਲ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ:

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

ਪਰ ਹੇਠਾਂ ਦਿੱਤੀਆਂ ਸਾਰੀਆਂ ਕਾਲਾਂ ਗਲਤ ਹੋਣਗੀਆਂ:

parrot()                     # required argument missing
parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor='John Cleese')  # unknown keyword argument

ਕਿਸੇ function call ਵਿੱਚ keyword arguments, positional arguments ਤੋਂ ਬਾਅਦ ਆਉਣੇ ਚਾਹੀਦੇ ਹਨ। ਪਾਸ ਕੀਤੇ ਗਏ ਸਾਰੇ keyword arguments function ਦੁਆਰਾ ਸਵੀਕਾਰ ਕੀਤੇ arguments ਵਿੱਚੋਂ ਕਿਸੇ ਇੱਕ ਨਾਲ ਮਿਲਣੇ ਚਾਹੀਦੇ ਹਨ (ਉਦਾਹਰਨ ਵਜੋਂ actor , parrot function ਲਈ ਵੈਧ argument ਨਹੀਂ ਹੈ), ਅਤੇ ਉਨ੍ਹਾਂ ਦਾ ਕ੍ਰਮ ਮਹੱਤਵਪੂਰਨ ਨਹੀਂ ਹੁੰਦਾ। ਇਹ ਨਿਯਮ non-optional arguments ਉੱਤੇ ਵੀ ਲਾਗੂ ਹੁੰਦਾ ਹੈ (ਉਦਾਹਰਨ ਲਈ parrot(voltage=1000) ਵੀ ਵੈਧ ਹੈ)। ਕਿਸੇ argument ਨੂੰ ਇੱਕ ਤੋਂ ਵੱਧ ਵਾਰ ਮੁੱਲ ਨਹੀਂ ਦਿੱਤਾ ਜਾ ਸਕਦਾ। ਹੇਠਾਂ ਇੱਕ ਉਦਾਹਰਨ ਹੈ ਜੋ ਇਸ ਪਾਬੰਦੀ ਕਾਰਨ ਅਸਫਲ ਹੋ ਜਾਂਦੀ ਹੈ:

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for argument 'a'

ਜਦੋਂ **name ਦੇ ਰੂਪ ਵਾਲਾ ਆਖਰੀ formal parameter ਮੌਜੂਦ ਹੋਵੇ, ਤਾਂ ਇਹ ਉਹ dictionary (ਵੇਖੋ Mapping types --- dict, frozendict) ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ ਜਿਸ ਵਿੱਚ ਉਹ ਸਾਰੇ keyword arguments ਹੁੰਦੇ ਹਨ ਜੋ ਕਿਸੇ formal parameter ਨਾਲ ਸੰਬੰਧਿਤ ਨਹੀਂ ਹੁੰਦੇ। ਇਸਨੂੰ *name ਰੂਪ ਵਾਲੇ formal parameter (ਜਿਸਦਾ ਵੇਰਵਾ ਅਗਲੇ subsection ਵਿੱਚ ਹੈ) ਨਾਲ ਜੋੜਿਆ ਜਾ ਸਕਦਾ ਹੈ, ਜੋ formal parameter list ਤੋਂ ਵੱਧ positional arguments ਵਾਲਾ tuple ਪ੍ਰਾਪਤ ਕਰਦਾ ਹੈ। (*name ਹਮੇਸ਼ਾਂ **name ਤੋਂ ਪਹਿਲਾਂ ਆਉਣਾ ਚਾਹੀਦਾ ਹੈ।) ਉਦਾਹਰਨ ਲਈ, ਜੇ ਅਸੀਂ function ਇਸ ਤਰ੍ਹਾਂ ਪਰਿਭਾਸ਼ਿਤ ਕਰੀਏ:

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])

ਇਸਨੂੰ ਇਸ ਤਰ੍ਹਾਂ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ:

cheeseshop("Limburger", "It's very runny, sir.",
           "It's really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")

ਅਤੇ ਬੇਸ਼ੱਕ ਇਹ ਇਹ ਪ੍ਰਿੰਟ ਕਰੇਗਾ:

-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch

ਧਿਆਨ ਦਿਓ ਕਿ keyword arguments ਜਿਸ ਕ੍ਰਮ ਵਿੱਚ ਪ੍ਰਿੰਟ ਕੀਤੇ ਜਾਂਦੇ ਹਨ, ਉਹਨਾਂ ਦਾ ਕ੍ਰਮ function call ਵਿੱਚ ਦਿੱਤੇ ਗਏ ਕ੍ਰਮ ਦੇ ਨਾਲ ਮਿਲਣ ਦੀ ਗਾਰੰਟੀ ਹੁੰਦੀ ਹੈ।

4.9.3. ਖਾਸ ਪੈਰਾਮੀਟਰ

ਮੂਲ ਰੂਪ ਵਿੱਚ arguments ਨੂੰ Python function ਵਿੱਚ positional ਤਰੀਕੇ ਨਾਲ ਜਾਂ ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ keyword ਰਾਹੀਂ ਪਾਸ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਪੜ੍ਹਨਯੋਗਤਾ ਅਤੇ ਕਾਰਗੁਜ਼ਾਰੀ ਲਈ ਇਹ ਲਾਭਦਾਇਕ ਹੁੰਦਾ ਹੈ ਕਿ arguments ਪਾਸ ਕਰਨ ਦੇ ਤਰੀਕੇ ਨੂੰ ਸੀਮਿਤ ਕੀਤਾ ਜਾਵੇ, ਤਾਂ ਜੋ developer ਸਿਰਫ਼ function definition ਵੇਖ ਕੇ ਸਮਝ ਸਕੇ ਕਿ items positional ਹਨ, positional ਜਾਂ keyword ਹਨ, ਜਾਂ ਸਿਰਫ਼ keyword ਹਨ।

ਕਿਸੇ function ਦੀ ਪਰਿਭਾਸ਼ਾ ਇਸ ਤਰ੍ਹਾਂ ਦਿਖ ਸਕਦੀ ਹੈ:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
      -----------    ----------     ----------
        |             |                  |
        |      Positional or keyword    |
        |                               - Keyword only
         -- Positional only

ਇੱਥੇ / ਅਤੇ * ਵਿਕਲਪਿਕ ਹਨ। ਜੇ ਇਹ ਵਰਤੇ ਜਾਣ, ਤਾਂ ਇਹ ਚਿੰਨ੍ਹ ਦਰਸਾਉਂਦੇ ਹਨ ਕਿ arguments function ਨੂੰ ਕਿਵੇਂ ਪਾਸ ਕੀਤੇ ਜਾ ਸਕਦੇ ਹਨ: ਕੇਵਲ positional, positional ਜਾਂ keyword, ਅਤੇ ਕੇਵਲ keyword। Keyword parameters ਨੂੰ named parameters ਵੀ ਕਿਹਾ ਜਾਂਦਾ ਹੈ।

4.9.3.1. Positional ਜਾਂ Keyword ਆਰਗਿਊਮੈਂਟ

ਜੇ function definition ਵਿੱਚ / ਅਤੇ * ਮੌਜੂਦ ਨਾ ਹੋਣ, ਤਾਂ arguments ਨੂੰ function ਵਿੱਚ positional ਜਾਂ keyword ਦੋਵੇਂ ਤਰੀਕਿਆਂ ਨਾਲ ਪਾਸ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।

4.9.3.2. ਕੇਵਲ Positional ਪੈਰਾਮੀਟਰ

ਇਸਨੂੰ ਥੋੜ੍ਹੇ ਹੋਰ ਵਿਸਥਾਰ ਨਾਲ ਵੇਖੀਏ ਤਾਂ ਕੁਝ parameters ਨੂੰ positional-only ਵਜੋਂ ਚਿੰਨ੍ਹਿਤ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ। ਜੇ parameter positional-only ਹੋਵੇ, ਤਾਂ ਉਸਦਾ ਕ੍ਰਮ ਮਹੱਤਵ ਰੱਖਦਾ ਹੈ ਅਤੇ ਉਸਨੂੰ keyword ਰਾਹੀਂ ਪਾਸ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ। Positional-only parameters ਨੂੰ / (forward-slash) ਤੋਂ ਪਹਿਲਾਂ ਰੱਖਿਆ ਜਾਂਦਾ ਹੈ। / positional-only parameters ਨੂੰ ਬਾਕੀ parameters ਤੋਂ ਤਰਕਸੰਗਤ ਤੌਰ 'ਤੇ ਵੱਖ ਕਰਨ ਲਈ ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ। ਜੇ function definition ਵਿੱਚ / ਨਾ ਹੋਵੇ, ਤਾਂ ਕੋਈ positional-only parameter ਨਹੀਂ ਹੁੰਦਾ।

/ ਤੋਂ ਬਾਅਦ ਆਉਣ ਵਾਲੇ parameters positional-or-keyword ਜਾਂ keyword-only ਹੋ ਸਕਦੇ ਹਨ।

4.9.3.3. ਕੇਵਲ Keyword ਆਰਗਿਊਮੈਂਟ

Parameters ਨੂੰ keyword-only ਵਜੋਂ ਚਿੰਨ੍ਹਿਤ ਕਰਨ ਲਈ, ਜਿਸਦਾ ਅਰਥ ਹੈ ਕਿ ਉਹ keyword argument ਰਾਹੀਂ ਹੀ ਪਾਸ ਕੀਤੇ ਜਾਣ, arguments list ਵਿੱਚ ਪਹਿਲੇ keyword-only parameter ਤੋਂ ਠੀਕ ਪਹਿਲਾਂ * ਰੱਖੋ।

4.9.3.4. ਫੰਕਸ਼ਨ ਉਦਾਹਰਨਾਂ

ਹੇਠਾਂ ਦਿੱਤੀਆਂ ਉਦਾਹਰਨ function definitions ਨੂੰ ਵੇਖੋ ਅਤੇ / ਅਤੇ * ਚਿੰਨ੍ਹਾਂ ਉੱਤੇ ਖ਼ਾਸ ਧਿਆਨ ਦਿਓ:

>>> def standard_arg(arg):
...     print(arg)
...
>>> def pos_only_arg(arg, /):
...     print(arg)
...
>>> def kwd_only_arg(*, arg):
...     print(arg)
...
>>> def combined_example(pos_only, /, standard, *, kwd_only):
...     print(pos_only, standard, kwd_only)

ਪਹਿਲੀ function definition standard_arg ਸਭ ਤੋਂ ਜਾਣੀ-ਪਹਿਚਾਣੀ ਰੂਪ-ਰੇਖਾ ਹੈ। ਇਹ calling convention ਉੱਤੇ ਕੋਈ ਪਾਬੰਦੀ ਨਹੀਂ ਲਗਾਉਂਦੀ ਅਤੇ arguments ਨੂੰ positional ਜਾਂ keyword ਦੋਵੇਂ ਤਰੀਕਿਆਂ ਨਾਲ ਪਾਸ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ:

>>> standard_arg(2)
2

>>> standard_arg(arg=2)
2

ਦੂਜੀ function pos_only_arg ਸਿਰਫ਼ positional parameters ਦੀ ਵਰਤੋਂ ਤੱਕ ਸੀਮਿਤ ਹੈ ਕਿਉਂਕਿ ਇਸਦੀ function definition ਵਿੱਚ / ਮੌਜੂਦ ਹੈ:

>>> pos_only_arg(1)
1

>>> pos_only_arg(arg=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'

ਤੀਜੀ function kwd_only_arg ਸਿਰਫ਼ keyword arguments ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ, ਜਿਵੇਂ ਕਿ function definition ਵਿੱਚ ਮੌਜੂਦ * ਦਰਸਾਉਂਦਾ ਹੈ:

>>> kwd_only_arg(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given

>>> kwd_only_arg(arg=3)
3

ਅਤੇ ਆਖਰੀ function ਇੱਕੋ function definition ਵਿੱਚ ਤਿੰਨਾਂ calling conventions ਦੀ ਵਰਤੋਂ ਕਰਦੀ ਹੈ:

>>> combined_example(1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: combined_example() takes 2 positional arguments but 3 were given

>>> combined_example(1, 2, kwd_only=3)
1 2 3

>>> combined_example(1, standard=2, kwd_only=3)
1 2 3

>>> combined_example(pos_only=1, standard=2, kwd_only=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'

ਅੰਤ ਵਿੱਚ, ਇਸ ਫੰਕਸ਼ਨ ਪਰਿਭਾਸ਼ਾ ਨੂੰ ਵੇਖੋ ਜਿਸ ਵਿੱਚ ਸਥਾਨ-ਅਧਾਰਿਤ ਦਲੀਲ name ਅਤੇ **kwds, ਜਿਸ ਵਿੱਚ name ਇੱਕ ਕੁੰਜੀ ਹੈ, ਵਿਚਕਾਰ ਸੰਭਾਵੀ ਟਕਰਾਅ ਹੈ:

def foo(name, **kwds):
    return 'name' in kwds

ਅਜਿਹੀ ਕੋਈ call ਸੰਭਵ ਨਹੀਂ ਜੋ ਇਸਨੂੰ True ਵਾਪਸ ਕਰਨ ਲਈ ਮਜਬੂਰ ਕਰੇ, ਕਿਉਂਕਿ keyword 'name' ਹਮੇਸ਼ਾਂ ਪਹਿਲੇ parameter ਨਾਲ bind ਹੋ ਜਾਵੇਗਾ। ਉਦਾਹਰਨ ਲਈ:

>>> foo(1, **{'name': 2})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got multiple values for argument 'name'
>>>

ਪਰ / (ਕੇਵਲ positional arguments) ਦੀ ਵਰਤੋਂ ਨਾਲ ਇਹ ਸੰਭਵ ਹੈ, ਕਿਉਂਕਿ ਇਹ name ਨੂੰ positional argument ਵਜੋਂ ਅਤੇ 'name' ਨੂੰ keyword arguments ਵਿੱਚ key ਵਜੋਂ ਵਰਤਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ:

>>> def foo(name, /, **kwds):
...     return 'name' in kwds
...
>>> foo(1, **{'name': 2})
True

ਦੂਜੇ ਸ਼ਬਦਾਂ ਵਿੱਚ, positional-only parameters ਦੇ ਨਾਮ **kwds ਵਿੱਚ ਬਿਨਾਂ ਕਿਸੇ ਅਸਪਸ਼ਟਤਾ ਦੇ ਵਰਤੇ ਜਾ ਸਕਦੇ ਹਨ।

4.9.3.5. ਸੰਖੇਪ ਪੁਨਰਾਵਲੋਕਨ

ਵਰਤੋਂ ਦੀ ਲੋੜ ਇਹ ਨਿਰਧਾਰਤ ਕਰੇਗੀ ਕਿ function definition ਵਿੱਚ ਕਿਹੜੇ parameters ਵਰਤਣੇ ਹਨ:

def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):

ਮਾਰਗਦਰਸ਼ਨ ਵਜੋਂ:

  • ਜੇ ਤੁਸੀਂ ਚਾਹੁੰਦੇ ਹੋ ਕਿ parameters ਦੇ ਨਾਮ ਵਰਤੋਂਕਾਰ ਲਈ ਉਪਲਬਧ ਨਾ ਹੋਣ, ਤਾਂ positional-only parameters ਵਰਤੋ। ਇਹ ਉਸ ਵੇਲੇ ਲਾਭਦਾਇਕ ਹੁੰਦਾ ਹੈ ਜਦੋਂ parameter names ਦਾ ਕੋਈ ਖ਼ਾਸ ਅਰਥ ਨਾ ਹੋਵੇ, ਜਦੋਂ ਤੁਸੀਂ function call ਦੌਰਾਨ arguments ਦੇ ਕ੍ਰਮ ਨੂੰ ਲਾਜ਼ਮੀ ਬਣਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਜਾਂ ਜਦੋਂ ਤੁਹਾਨੂੰ ਕੁਝ positional parameters ਅਤੇ ਮਨਮਾਨੇ keywords ਸਵੀਕਾਰ ਕਰਨੇ ਹੋਣ।

  • ਜਦੋਂ names ਦਾ ਅਰਥਪੂਰਨ ਮਹੱਤਵ ਹੋਵੇ ਅਤੇ function definition ਨਾਮਾਂ ਨੂੰ ਸਪਸ਼ਟ ਰੱਖਣ ਨਾਲ ਹੋਰ ਸਮਝਣਯੋਗ ਬਣਦੀ ਹੋਵੇ, ਜਾਂ ਤੁਸੀਂ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ arguments ਦੀ position ਉੱਤੇ ਨਿਰਭਰ ਕਰਨ ਤੋਂ ਰੋਕਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ keyword-only parameters ਵਰਤੋ।

  • ਕਿਸੇ API ਲਈ positional-only parameters ਵਰਤੋ ਤਾਂ ਜੋ ਭਵਿੱਖ ਵਿੱਚ parameter ਦਾ ਨਾਮ ਬਦਲਣ ਨਾਲ API ਦੀ ਅਨੁਕੂਲਤਾ ਨਾ ਟੁੱਟੇ।

4.9.4. ਮਨਮਾਨੀਆਂ ਆਰਗਿਊਮੈਂਟ ਸੂਚੀਆਂ

ਅੰਤ ਵਿੱਚ, ਸਭ ਤੋਂ ਘੱਟ ਵਰਤਿਆ ਜਾਣ ਵਾਲਾ ਵਿਕਲਪ ਇਹ ਹੈ ਕਿ function ਨੂੰ ਮਨਮਾਨੀ ਗਿਣਤੀ ਦੇ arguments ਨਾਲ ਕਾਲ ਕੀਤਾ ਜਾ ਸਕੇ। ਇਹ arguments ਇੱਕ tuple ਵਿੱਚ ਸਮੇਟੇ ਜਾਂਦੇ ਹਨ (ਵੇਖੋ ਟਿਊਪਲ ਅਤੇ ਕ੍ਰਮ)। Variable ਗਿਣਤੀ ਵਾਲੇ arguments ਤੋਂ ਪਹਿਲਾਂ ਸ਼ੂਨ੍ਯ ਜਾਂ ਇੱਕ ਤੋਂ ਵੱਧ ਆਮ arguments ਹੋ ਸਕਦੇ ਹਨ.

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

ਆਮ ਤੌਰ 'ਤੇ ਇਹ variadic arguments formal parameters ਦੀ ਸੂਚੀ ਦੇ ਅੰਤ ਵਿੱਚ ਹੁੰਦੇ ਹਨ, ਕਿਉਂਕਿ ਇਹ function ਨੂੰ ਪਾਸ ਕੀਤੇ ਗਏ ਸਾਰੇ ਬਾਕੀ input arguments ਨੂੰ ਇਕੱਠਾ ਕਰ ਲੈਂਦੇ ਹਨ। *args parameter ਤੋਂ ਬਾਅਦ ਆਉਣ ਵਾਲੇ ਸਾਰੇ formal parameters 'keyword-only' ਹੁੰਦੇ ਹਨ, ਜਿਸਦਾ ਅਰਥ ਹੈ ਕਿ ਉਹਨਾਂ ਨੂੰ ਸਿਰਫ਼ keywords ਵਜੋਂ ਹੀ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ, positional arguments ਵਜੋਂ ਨਹੀਂ।

>>> def concat(*args, sep="/"):
...     return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'

4.9.5. ਆਰਗਿਊਮੈਂਟ ਸੂਚੀਆਂ ਦਾ Unpacking

ਉਲਟੀ ਸਥਿਤੀ ਉਸ ਵੇਲੇ ਹੁੰਦੀ ਹੈ ਜਦੋਂ arguments ਪਹਿਲਾਂ ਹੀ ਕਿਸੇ list ਜਾਂ tuple ਵਿੱਚ ਹੋਣ, ਪਰ ਉਹਨਾਂ ਨੂੰ ਵੱਖਰੇ positional arguments ਦੀ ਲੋੜ ਵਾਲੀ function call ਲਈ unpack ਕਰਨਾ ਪਵੇ। ਉਦਾਹਰਨ ਵਜੋਂ built-in range() function ਵੱਖਰੇ start ਅਤੇ stop arguments ਦੀ ਉਮੀਦ ਕਰਦਾ ਹੈ। ਜੇ ਉਹ ਵੱਖਰੇ ਤੌਰ 'ਤੇ ਉਪਲਬਧ ਨਾ ਹੋਣ, ਤਾਂ list ਜਾਂ tuple ਵਿੱਚੋਂ arguments ਨੂੰ unpack ਕਰਨ ਲਈ * operator ਵਰਤੋ:

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]

ਇਸੇ ਤਰ੍ਹਾਂ dictionaries ਵੀ ** operator ਦੀ ਮਦਦ ਨਾਲ keyword arguments ਪ੍ਰਦਾਨ ਕਰ ਸਕਦੀਆਂ ਹਨ:

>>> def parrot(voltage, state='a stiff', action='voom'):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.", end=' ')
...     print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !

4.9.6. Lambda ਐਕਸਪ੍ਰੈਸ਼ਨ

ਛੋਟੇ anonymous functions ਨੂੰ lambda keyword ਦੀ ਵਰਤੋਂ ਨਾਲ ਬਣਾਇਆ ਜਾ ਸਕਦਾ ਹੈ। ਇਹ function ਆਪਣੇ ਦੋ arguments ਦਾ ਜੋੜ ਵਾਪਸ ਕਰਦਾ ਹੈ: lambda a, b: a+b। Lambda functions ਨੂੰ ਉੱਥੇ ਵਰਤਿਆ ਜਾ ਸਕਦਾ ਹੈ ਜਿੱਥੇ function objects ਦੀ ਲੋੜ ਹੋਵੇ। Syntax ਦੇ ਹਿਸਾਬ ਨਾਲ ਇਹ ਇੱਕ ਹੀ expression ਤੱਕ ਸੀਮਿਤ ਹੁੰਦੇ ਹਨ। ਅਰਥਾਤ, ਇਹ ਆਮ function definition ਲਈ ਇੱਕ ਸੁਵਿਧਾਜਨਕ shorthand ਹਨ। Nested function definitions ਦੀ ਤਰ੍ਹਾਂ, lambda functions ਵੀ enclosing scope ਦੇ variables ਨੂੰ reference ਕਰ ਸਕਦੇ ਹਨ:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

ਉਪਰੋਕਤ ਉਦਾਹਰਨ ਵਿੱਚ ਇੱਕ lambda expression ਦੀ ਵਰਤੋਂ function ਵਾਪਸ ਕਰਨ ਲਈ ਕੀਤੀ ਗਈ ਹੈ। ਇਸਦੀ ਇੱਕ ਹੋਰ ਵਰਤੋਂ ਇੱਕ ਛੋਟੇ function ਨੂੰ argument ਵਜੋਂ ਪਾਸ ਕਰਨਾ ਹੈ। ਉਦਾਹਰਨ ਲਈ, list.sort() ਇੱਕ sorting key function key ਲੈਂਦਾ ਹੈ ਜੋ lambda function ਹੋ ਸਕਦਾ ਹੈ:

>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]

4.9.7. ਡਾਕੂਮੈਂਟੇਸ਼ਨ ਸਟ੍ਰਿੰਗਾਂ

ਡਾਕੂਮੈਂਟੇਸ਼ਨ ਸਟ੍ਰਿੰਗਾਂ ਦੀ ਸਮੱਗਰੀ ਅਤੇ ਫਾਰਮੈਟਿੰਗ ਬਾਰੇ ਕੁਝ ਆਮ ਪਰੰਪਰਾਵਾਂ ਹੇਠਾਂ ਦਿੱਤੀਆਂ ਗਈਆਂ ਹਨ।

ਪਹਿਲੀ ਲਾਈਨ ਹਮੇਸ਼ਾਂ object ਦੇ ਉਦੇਸ਼ ਦਾ ਇੱਕ ਛੋਟਾ ਅਤੇ ਸੰਖੇਪ ਸਾਰ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ। ਸੰਖੇਪਤਾ ਲਈ ਇਸ ਵਿੱਚ object ਦਾ ਨਾਮ ਜਾਂ type ਸਪਸ਼ਟ ਤੌਰ 'ਤੇ ਨਹੀਂ ਦੱਸਣਾ ਚਾਹੀਦਾ, ਕਿਉਂਕਿ ਇਹ ਜਾਣਕਾਰੀ ਹੋਰ ਤਰੀਕਿਆਂ ਨਾਲ ਉਪਲਬਧ ਹੁੰਦੀ ਹੈ (ਸਿਵਾਏ ਉਸ ਸਥਿਤੀ ਦੇ ਜਦੋਂ ਨਾਮ ਕਿਸੇ function ਦੀ ਕਾਰਵਾਈ ਨੂੰ ਦਰਸਾਉਣ ਵਾਲਾ verb ਹੋਵੇ)। ਇਹ ਲਾਈਨ ਵੱਡੇ ਅੱਖਰ ਨਾਲ ਸ਼ੁਰੂ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ ਅਤੇ period ਨਾਲ ਸਮਾਪਤ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ।

ਜੇ documentation string ਵਿੱਚ ਹੋਰ ਲਾਈਨਾਂ ਹਨ, ਤਾਂ ਦੂਜੀ ਲਾਈਨ ਖਾਲੀ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ ਤਾਂ ਜੋ summary ਅਤੇ ਬਾਕੀ ਵੇਰਵੇ ਵਿਚਕਾਰ ਸਪਸ਼ਟ ਵੱਖਰਾ ਦਿਸੇ। ਇਸ ਤੋਂ ਬਾਅਦ ਵਾਲੀਆਂ ਲਾਈਨਾਂ ਵਿੱਚ ਇੱਕ ਜਾਂ ਵੱਧ paragraphs ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ ਜੋ object ਦੀ calling conventions, side effects ਅਤੇ ਹੋਰ ਵੇਰਵਿਆਂ ਦਾ ਵਰਣਨ ਕਰਨ।

ਜਦੋਂ multi-line string literals module, class ਜਾਂ function docstrings ਵਜੋਂ ਵਰਤੇ ਜਾਂਦੇ ਹਨ, ਤਾਂ Python parser ਉਹਨਾਂ ਵਿਚੋਂ indentation ਹਟਾ ਦਿੰਦਾ ਹੈ।

ਇੱਥੇ ਇੱਕ multi-line docstring ਦੀ ਉਦਾਹਰਨ ਹੈ:

>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn't do anything:
...
...         >>> my_function()
...         >>>
...     """
...     pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

No, really, it doesn't do anything:

    >>> my_function()
    >>>

4.9.8. ਫੰਕਸ਼ਨ ਐਨੋਟੇਸ਼ਨ

Function annotations ਵਰਤੋਂਕਾਰ ਦੁਆਰਾ ਪਰਿਭਾਸ਼ਿਤ functions ਵਿੱਚ ਵਰਤੀਆਂ ਗਈਆਂ types ਬਾਰੇ ਪੂਰੀ ਤਰ੍ਹਾਂ ਵਿਕਲਪਿਕ metadata ਜਾਣਕਾਰੀ ਹੁੰਦੀ ਹੈ (ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ PEP 3107 ਅਤੇ PEP 484 ਵੇਖੋ)।

Annotations function ਦੇ __annotations__ attribute ਵਿੱਚ dictionary ਦੇ ਰੂਪ ਵਿੱਚ ਸੰਭਾਲੀਆਂ ਜਾਂਦੀਆਂ ਹਨ ਅਤੇ function ਦੇ ਕਿਸੇ ਹੋਰ ਹਿੱਸੇ ਉੱਤੇ ਕੋਈ ਪ੍ਰਭਾਵ ਨਹੀਂ ਪਾਂਦੀਆਂ। Parameter annotations parameter ਦੇ ਨਾਮ ਤੋਂ ਬਾਅਦ colon ਲਗਾ ਕੇ ਅਤੇ annotation ਦੇ ਮੁੱਲ ਵਿੱਚ evaluate ਹੋਣ ਵਾਲੀ expression ਦੇ ਕੇ ਪਰਿਭਾਸ਼ਿਤ ਕੀਤੀਆਂ ਜਾਂਦੀਆਂ ਹਨ। Return annotations ਨੂੰ literal -> ਰਾਹੀਂ, parameter list ਅਤੇ def statement ਦੇ ਅੰਤ ਨੂੰ ਦਰਸਾਉਣ ਵਾਲੇ colon ਦੇ ਵਿਚਕਾਰ, ਇੱਕ expression ਨਾਲ ਪਰਿਭਾਸ਼ਿਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਹੇਠਾਂ ਦਿੱਤੀ ਉਦਾਹਰਨ ਵਿੱਚ ਇੱਕ ਲਾਜ਼ਮੀ argument, ਇੱਕ ਵਿਕਲਪਿਕ argument ਅਤੇ return value annotated ਹਨ:

>>> def f(ham: str, eggs: str = 'eggs') -> str:
...     print("Annotations:", f.__annotations__)
...     print("Arguments:", ham, eggs)
...     return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'

4.10. ਵਿਚਕਾਰਲੀ ਚਰਚਾ: ਕੋਡਿੰਗ ਸ਼ੈਲੀ

ਹੁਣ ਜਦੋਂ ਤੁਸੀਂ Python ਦੇ ਹੋਰ ਲੰਬੇ ਅਤੇ ਜਟਿਲ ਪ੍ਰੋਗਰਾਮ ਲਿਖਣ ਵਾਲੇ ਹੋ, ਤਾਂ coding style ਬਾਰੇ ਗੱਲ ਕਰਨ ਦਾ ਇਹ ਚੰਗਾ ਸਮਾਂ ਹੈ। ਬਹੁਤੀਆਂ ਭਾਸ਼ਾਵਾਂ ਨੂੰ ਵੱਖ-ਵੱਖ styles ਵਿੱਚ ਲਿਖਿਆ (ਜਾਂ ਹੋਰ ਸੰਖੇਪ ਵਿੱਚ ਕਹੀਏ ਤਾਂ format ਕੀਤਾ) ਜਾ ਸਕਦਾ ਹੈ; ਕੁਝ styles ਹੋਰਾਂ ਨਾਲੋਂ ਵੱਧ ਪੜ੍ਹਨਯੋਗ ਹੁੰਦੀਆਂ ਹਨ। ਆਪਣੇ code ਨੂੰ ਹੋਰਾਂ ਲਈ ਪੜ੍ਹਨਾ ਆਸਾਨ ਬਣਾਉਣਾ ਹਮੇਸ਼ਾਂ ਚੰਗਾ ਵਿਚਾਰ ਹੈ, ਅਤੇ ਵਧੀਆ coding style ਅਪਣਾਉਣ ਨਾਲ ਇਸ ਵਿੱਚ ਬਹੁਤ ਮਦਦ ਮਿਲਦੀ ਹੈ।

Python ਲਈ PEP 8 ਉਹ style guide ਬਣ ਚੁੱਕੀ ਹੈ ਜਿਸਦੀ ਬਹੁਤੇ projects ਪਾਲਣਾ ਕਰਦੇ ਹਨ; ਇਹ ਬਹੁਤ ਪੜ੍ਹਨਯੋਗ ਅਤੇ ਸੁੰਦਰ coding style ਨੂੰ ਉਤਸ਼ਾਹਿਤ ਕਰਦੀ ਹੈ। ਹਰ Python developer ਨੂੰ ਕਿਸੇ ਨਾ ਕਿਸੇ ਸਮੇਂ ਇਸਨੂੰ ਪੜ੍ਹਣਾ ਚਾਹੀਦਾ ਹੈ; ਹੇਠਾਂ ਤੁਹਾਡੇ ਲਈ ਇਸਦੇ ਸਭ ਤੋਂ ਮਹੱਤਵਪੂਰਨ ਬਿੰਦੂ ਦਿੱਤੇ ਗਏ ਹਨ:

  • 4 spaces ਦੀ indentation ਵਰਤੋ ਅਤੇ tabs ਨਾ ਵਰਤੋ।

    4 spaces ਛੋਟੀ indentation (ਜਿਸ ਨਾਲ ਵੱਧ nesting depth ਮਿਲਦੀ ਹੈ) ਅਤੇ ਵੱਡੀ indentation (ਜਿਸ ਨਾਲ ਪੜ੍ਹਨਾ ਆਸਾਨ ਹੁੰਦਾ ਹੈ) ਵਿਚਕਾਰ ਇੱਕ ਵਧੀਆ ਸੰਤੁਲਨ ਹੈ। Tabs ਉਲਝਣ ਪੈਦਾ ਕਰਦੀਆਂ ਹਨ, ਇਸ ਲਈ ਉਹਨਾਂ ਤੋਂ ਬਚਣਾ ਚੰਗਾ ਹੈ।

  • ਲਾਈਨਾਂ ਨੂੰ ਇਸ ਤਰ੍ਹਾਂ wrap ਕਰੋ ਕਿ ਉਹ 79 ਅੱਖਰਾਂ ਤੋਂ ਵੱਧ ਨਾ ਜਾਣ।

    ਇਸ ਨਾਲ ਛੋਟੀ ਸਕ੍ਰੀਨਾਂ ਵਾਲੇ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਮਦਦ ਮਿਲਦੀ ਹੈ ਅਤੇ ਵੱਡੀਆਂ ਸਕ੍ਰੀਨਾਂ ਉੱਤੇ ਕਈ code files ਨੂੰ ਇਕੱਠੇ ਵੇਖਣਾ ਸੰਭਵ ਹੁੰਦਾ ਹੈ।

  • Functions ਅਤੇ classes ਨੂੰ ਵੱਖ ਕਰਨ ਲਈ ਖਾਲੀ ਲਾਈਨਾਂ ਵਰਤੋ, ਅਤੇ functions ਦੇ ਅੰਦਰ code ਦੇ ਵੱਡੇ blocks ਨੂੰ ਵੀ ਖਾਲੀ ਲਾਈਨਾਂ ਨਾਲ ਵੱਖ ਕਰੋ।

  • ਜਿੱਥੇ ਸੰਭਵ ਹੋਵੇ, comments ਨੂੰ ਉਹਨਾਂ ਦੀ ਆਪਣੀ ਲਾਈਨ ਉੱਤੇ ਲਿਖੋ।

  • Docstrings ਦੀ ਵਰਤੋਂ ਕਰੋ।

  • Operators ਦੇ ਆਲੇ-ਦੁਆਲੇ ਅਤੇ commas ਤੋਂ ਬਾਅਦ spaces ਵਰਤੋ, ਪਰ brackets ਦੇ ਅੰਦਰ ਸਿੱਧੇ space ਨਾ ਦਿਓ: a = f(1, 2) + g(3, 4)।

  • ਆਪਣੀਆਂ classes ਅਤੇ functions ਦੇ ਨਾਮ ਇਕਸਾਰ ਰੱਖੋ; ਰਵਾਇਤ ਅਨੁਸਾਰ classes ਲਈ UpperCamelCase ਅਤੇ functions ਅਤੇ methods ਲਈ lowercase_with_underscores ਵਰਤਿਆ ਜਾਂਦਾ ਹੈ। ਪਹਿਲੇ method argument ਦਾ ਨਾਮ ਹਮੇਸ਼ਾਂ self ਰੱਖੋ (classes ਅਤੇ methods ਬਾਰੇ ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਕਲਾਸਾਂ ਨਾਲ ਪਹਿਲੀ ਜਾਣ-ਪਛਾਣ ਵੇਖੋ)।

  • ਜੇ ਤੁਹਾਡਾ code ਅੰਤਰਰਾਸ਼ਟਰੀ ਮਾਹੌਲ ਵਿੱਚ ਵਰਤਿਆ ਜਾਣਾ ਹੈ ਤਾਂ ਜਟਿਲ encodings ਨਾ ਵਰਤੋ। Python ਦਾ ਮੂਲ UTF-8 ਜਾਂ ਸਧਾਰਣ ASCII ਹਰ ਹਾਲਤ ਵਿੱਚ ਸਭ ਤੋਂ ਵਧੀਆ ਕੰਮ ਕਰਦੇ ਹਨ।

  • ਇਸੇ ਤਰ੍ਹਾਂ, identifiers ਵਿੱਚ non-ASCII ਅੱਖਰਾਂ ਦੀ ਵਰਤੋਂ ਨਾ ਕਰੋ ਜੇ ਥੋੜ੍ਹੀ ਵੀ ਸੰਭਾਵਨਾ ਹੋਵੇ ਕਿ ਵੱਖਰੀ ਭਾਸ਼ਾ ਬੋਲਣ ਵਾਲੇ ਲੋਕ code ਨੂੰ ਪੜ੍ਹਣ ਜਾਂ ਸੰਭਾਲਣਗੇ।

ਫੁੱਟਨੋਟ