Видимість змінних.

Основи Python и Django. -> Видимість змінних.

# Область видимості змінних.

Глобальні та локальні змінні

Змінні діляться на локальні та глобальні залежно від того, де програма вона визначена.

Ці області називаються namespace (простір імен) та існують у всіх мовах програмування.

Основне їхнє завдання ізолювати змінні в різних частинах програми і не допустити конфліктів, якщо два розробники назвуть змінну одним і тим же ім’ям.

Давайте подивимося на таку функцію:

def f(): 
    print s 
s = "I hate spam"
f()

Змінна s визначена як рядкова перед тим, як ми викликаємо функцію f().

Так як всередині функції змінна s не визначена, використовуватиметься змінна, визначена у глобальному просторі - поза всякими функціями.

Питання — а якщо визначити змінну s всередині функції?

def f(): 
    s = "Me too."
    print s

s = "I hate spam." 
f()
print s

Висновок буде наступний:

Me too.
I hate spam.

У першому рядку використовується локальна змінна, визначена всередині функції, а в другому та, що визначена глобально.

Що якщо ми скомбінуємо ці два підходи так:

def f(): 
    print s
    s = "Me too."
    print s


s = "I hate spam." 
f()
print s

Усередині функції спочатку намагаємося вивести змінну з глобального простору, а потім, після ініціалізації всередині функції, з локального.

В результаті отримуємо виняток:

UnboundLocalError: local variable 's' referenced before assignment

Python вважає, що ми намагаємося на початку використовувати локальну змінну тому, що бачить, що вона визначена пізніше, тому викликає помилку.

Будь-яка змінна, яка змінюється чи створюється всередині функції, — локальна, якщо вона явно не визначена як глобальна за допомогою ключового слова global.

Приклад використання global.

def f():
    global s
    print s
    s = "That's clear."
    print s


s = "Python is great!" 
f()
print s

Тепер у нас відсутня невизначеність і висновок буде таким:

Python is great!
That's clear.
That's clear.

Локальні змінні або функції не можуть бути отримані ззовні, наприклад:

def f():
    s = "I am globally not known"
    print s

f()
print s

Цей код викликає такий виняток:

Traceback (most recent call last):
  File "global_local3.py", line 6, in <module>
    print s
NameError: name 's' is not defined

Перевірка існування змінної в локальної чи глобальної області видимості.

Як перевірити факт існування змінної чи функції?

І тому існують функції globals() і locals(), які повернуть список всіх змінних у відповідній області.

if 'myVar' in locals():
    print «myVar exists».


if 'myVar' in globals():
    # myVar exists.

Перевірка існування атрибута об’єкта:

if hasattr(obj, 'attr_name'):
    print „obj.attr_name exists“.

Отримання атрибуту.

m =  getattr(c, "say", None)

Перевірка є аттрибут методом.

m =  getattr(c, "say", None)
if callable(m):
    print 'Say is the function!!!'

Просто імен (namespace) - це, по суті, колекція всіх імен змінних. Всі вбудовані в Python функції знаходяться в глобальному просторі програми, тому доступні з будь-якої її точки. Кожен модуль (файл) створює свій власний глобальний простір, а кожна функція в модулі створює своє локальне. Таким чином, під час виконання програми ми маємо безліч просторів імен абсолютно ізольованих один від одного. На першому місці йде вбудований глобальний простір інтерпретатора Python? Звідки змінні доступні з будь-якого місця. Потім простір модуля і нарешті простір функцій. Кожен простір описується поняттям scope. Scope - ця область, що виділяється програмною сутністю (модулем, функцією, методом і т.д.) для зберігання змінних. При визначенні вкладених функцій, наприклад:

def outer_function():
    b = 20
    def inner_func():
        c = 30

Для кожної з них буде визначено свій scope. Сукупність scopе-ів має ієрархію (вкладеність). При спробі отримати доступ до тієї чи іншої змінної функції, інтерпретатор здійснює пошук по scope-ам починаючи від найбільш локального простору по відношенню місця, з якого здійснюється доступ і закінчуючи глобальним просторам інтерпретатора.

Приклад нижче демонструє цей принцип:

def outer_function():
    a = 20
    def inner_function():
        a = 30
        print('a =',a)

    inner_function()
    print('a =',a)

a = 10
outer_function()
print('a =',a)

Висновок:

a = 30
a = 20
a = 10
Основи Python и Django. -> Логування.

Логування в Python.

Створення логів є невід’ємною частиною проектування складних програм.

За допомогою ліг розробник може проаналізувати хід виконання програми і виявити її проблемні ділянки.

За роботу із логами відповідає внутрішній модуль logging.

import logging

Найкращою практикою буде створення об’єкта логера з використанням службової змінної name, яка позначає місце використання логера.

loger = logging.getLogger(__name__)

Існує кілька рівнів логування в залежності від важливості події для логера.

DEBUG: Найнижчий рівень для налагодження. INFO: Загальна інформація щодо роботи системи. WARNING: Інформація про незначні проблеми. ERROR:Інформація про основні суттєві помилки. CRITICAL:Критичні проблеми.

Встановлення рівня та виведення лога.

logging.basicConfig(level=logging.DEBUG)
logger.info('Start reading database')

Запис лога у файл установкою обробника FileHandler.

handler = logging.FileHandler('hello.log')
logger.addHandler(handler)

Форматування лога.

formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)

Існує багато обробників логів, включаючи посилання лога на email і навіть на віддалений сервер.

Ви можете написати власний обробник.

try:
    open('/path/to/does/not/exist', 'rb')
except (SystemExit, KeyboardInterrupt):
    raise
except Exception, e:
    logger.error('Failed to open file', exc_info=True)

Конфігурація логера словником.

import logging.config

logging.config.dictConfig({
    'version': 1,              
    'disable_existing_loggers': False,

    'formatters': {
        'standard': {
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': {
        'default': {
            'level':'INFO',    
            'class':'logging.StreamHandler',
        },  
        'file': {
            'level':'INFO',    
            'class':'logging.FileHandler',
            'filename': 'root.log',
        }, 
    },
    'loggers': {
        '': {                  
            'handlers': ['file'],        
            'level': 'INFO',  
            'propagate': True  
        }
    }
})

Фільтри.

Класи фільтра дозволяють фільтрувати певні повідомлення за умовою.

Наступний приклад демонструє фільтр, що відсіює всі повідомлення, крім тих, що мають рівень INFO.

import logging

class InfoFilter(logging.Filter):
    def filter(self, rec):
        return rec.levelno == logging.INFO

 'filters': {
     'my_filter': {
         '()': 'mymodule.InfoFilter'
     }
 },

 'mail_admins': {
     'level': 'ERROR',
     'filters': ['my_filter'],
     'class': 'django.utils.log.AdminEmailHandler'
 }

http://victorlin.me/posts/2012/08/26/good-logging-practice-in-python

Основи Python и Django. -> Тернарний оператор.

Тернарний оператор.

Тернарний оператор (Ternary operator) – використовується в рядок завдання умов присвоєння значення змінної.

Це укорочений варіант конструкції if-else.

[ontrue] if [expression] else [onfalse]

x, y = 50, 25
small = x if x < y else y

Тернарний оператор (Ternary operator) – використовується в рядок завдання умов присвоєння значення змінної.

cat_say = 'Mew'
me_say = 'Hi,cat' if cat_say == 'Mew' or cat_say == 'Myavki' else 'Who are you?'
print(me_say)
Hi,cat #результат

Приклад надання логічного значення

m = 1>3 or 7
Основи Python и Django. -> Основи роботи з GIT репозиторієм.

Основи роботи із GIT репозиторієм.

Встановлення клінтської програми на комп’ютер.

sudo apt install git

Створення репозиторію локально.

git init

При цьому створюється прпка .git.

Клонування існуючого репозиторію локально.

git clone path_to_repo

При цьому може використовуватися 2 протоколи передачі ssh і https.

При використанні ssh необхідно згенерувати ключі (якщо вони не були згенеровані) командою

ssh-keygen

Вивести публічний ключ на екран можна командою

cat ~/.ssh/id_rsa.pub

Потім скопіювати та вставити в інтерфейсі git провайдера.

Для github це Settings->SSH and GPG keys.

Перегляд стану репозиторію.

git status

Додавання файлів для відстеження.

git add .
git add --all
git add filename

–all -додає також приділені

Видалення файлів із відстеження.

git rm filename

Ігнорування файлів/директорів.

Виготовляється з тими файлами, які не змінюються в процесі розробки (зображення, папки редакторів та ін.)

Правила ігнорування описуються у файлі .gitignore наприклад:

venv
*.pyc
.vscode

Так само з репозиторію виключаються та ігноруються файли, що містять конфіденційну інформацію (ключі, паролі та ін.).

Коміт змін локально.

git commit -m 'conmmet text'

Прикріплення локального репозиторію до віддаленого.

Виробляється один раз після створення на GIT-сервері провайдера.

git remote add origin git@github.com:zdimon/test.git

Завантаження файлів на сервер із створенням master гілки.

git push -u origin master

Проводиться також один раз при створенні.

Надалі застосовується команда

git push

Оновлення репозиторію (актуалізування).

git pull

Створення нової гілки.

git branch branch_name

Перехід на гілку чи коміт.

git checkout branch_name_or_commit_id

Злиття гілки.

git merge branch_name

При цьому код із гілки branch_name зливається з поточної.