""" Урок 38. Функции. Области видимости — весь код примеров одним файлом. Источник: subjects/python-fundamentals/course/lessons/38-functions-scope/examples.html Файл собран автоматически (tools/build_lesson_examples.py): правьте страницу урока. Запуск: python lesson-38.py """ # ==================================================================== # Пример 1. def, return и None # ==================================================================== # 01_def_return.py def greet(name): return f"Hello, {name}!" def validate_data(): pass # заготовка: интерфейс понятен, реализации пока нет print(greet("Alice")) # Hello, Alice! print(validate_data()) # None # ==================================================================== # Пример 2. Позиционные, именованные и default-аргументы # ==================================================================== # 02_positional_named.py def describe(name, age, greeting="Hello"): return f"{greeting}, {name}! Age: {age}" print(describe("Bob", 30)) # Hello, Bob! Age: 30 print(describe(age=25, name="Alice", greeting="Hi")) # Hi, Alice! Age: 25 print(describe("Carol", greeting="Hey", age=40)) # Hey, Carol! Age: 40 # ==================================================================== # Пример 3. Порядок параметров: default — только после обязательных # ==================================================================== # 03_default_order.py try: exec("def bad(greeting='Hello', name): pass") except SyntaxError as error: print("SyntaxError:", error) # SyntaxError: non-default argument follows default argument (, line 1) # ==================================================================== # Пример 4. *args — упаковка позиционных аргументов # ==================================================================== # 04_args.py def show_numbers(*args): print(args, type(args)) show_numbers(1, 2, 3) # (1, 2, 3) show_numbers() # () def sum_all(*args): return sum(args) print(sum_all(1, 2, 3, 4)) # 10 # ==================================================================== # Пример 5. **kwargs — упаковка именованных аргументов # ==================================================================== # 05_kwargs.py def show_info(**kwargs): print(kwargs, type(kwargs)) show_info(name="Alice", age=25, city="Paris") # {'name': 'Alice', 'age': 25, 'city': 'Paris'} # ==================================================================== # Пример 6. Полный порядок параметров в одной функции # ==================================================================== # 06_combined_order.py def show_full_info(name, *details, age=25, **extra): return name, details, age, extra print(show_full_info("Alice", "Developer", age=30, city="New York")) # ('Alice', ('Developer',), 30, {'city': 'New York'}) print(show_full_info("Bob")) # ('Bob', (), 25, {}) # ==================================================================== # Пример 7. Распаковка при вызове функции # ==================================================================== # 07_unpacking_call.py def add(a, b, c): return a + b + c nums = (1, 2, 3) print(add(*nums)) # 6 def show_person(name, age, city): print(name, age, city) person = {"name": "Bob", "age": 30, "city": "London"} show_person(**person) # Bob 30 London # ==================================================================== # Пример 8. Только позиционные (/) и только именованные (*) # ==================================================================== # 08_positional_keyword_only.py def example(a, b, /, c, *, d): return a, b, c, d print(example(1, 2, 3, d=4)) # (1, 2, 3, 4) try: example(a=1, b=2, c=3, d=4) # a, b — только позиционные except TypeError as error: print("TypeError:", error) # TypeError: example() got some positional-only arguments passed as keyword arguments: 'a, b' try: example(1, 2, 3, 4) # d — только именованный except TypeError as error: print("TypeError:", error) # TypeError: example() takes 3 positional arguments but 4 were given # ==================================================================== # Пример 9. LEGB: порядок поиска имени # ==================================================================== # 09_legb.py z = "global z" def outer(): x = "enclosing x" def inner(): y = "local y" print(y, x, z, len) # local, enclosing, global, built-in inner() outer() # local y enclosing x global z # ==================================================================== # Пример 10. global — изменение глобальной переменной # ==================================================================== # 10_global.py counter = 0 def increment_counter(): global counter counter += 1 print("до:", counter) # до: 0 increment_counter() increment_counter() print("после:", counter) # после: 2 def try_increment_without_global(): counter = counter + 1 # counter уже считается локальной из-за присваивания ниже try: try_increment_without_global() except UnboundLocalError as error: print("UnboundLocalError:", error) # UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value # ==================================================================== # Пример 11. nonlocal — изменение переменной внешней функции # ==================================================================== # 11_nonlocal.py def make_accumulator(): total = 0 def add_value(value): nonlocal total total += value return total return add_value accumulate = make_accumulator() print(accumulate(10)) # 10 print(accumulate(5)) # 15 print(accumulate(1)) # 16 # ==================================================================== # Пример 12. Ловушка: изменяемое значение по умолчанию # ==================================================================== # 12_mutable_default.py def append_bad(value, items=[]): items.append(value) return items print(append_bad(1)) # [1] print(append_bad(2)) # [1, 2] — список "запомнил" предыдущий вызов! def append_good(value, items=None): if items is None: items = [] items.append(value) return items print(append_good(1)) # [1] print(append_good(2)) # [2]