Архив рубрики: Python

Пространства имен в Python

Namespaces are one honking great idea — let's do more of those!

The Zen of Python, by Tim Peters

Как известно, в Python есть локальные пространства имен (внутри функции или класса, которые могут быть вложенными), глобальное (на уровне текущего модуля) и встроенное пространство имен модуля builtins. К последнему Python обращается в последнюю очередь, если искомое имя не находится в локальном и глобальном пространствах имен.

Посмотрим на пространства имен Python в интерактивном режиме.

C:_dev> python.exe
Python 3.6.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> __name__
'__main__'

Это имя текущего модуля, в глобальном пространстве имен которого мы сейчас находимся. А функция dir() без аргументов покажет нам и другие имеющиеся в нем имена:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Попробуем увидеть, что за ними стоит. Нам помогут цикл for и eval():

>>> for name in dir(): print(name, eval(name), eval('type('+name+')'))
...
__annotations__ {}
__builtins__
__doc__ None
__loader__
__name__ __main__
__package__ None
__spec__ None

Приблизительно такую же информацию можно получить при помощи встроенной функции loclas(), которая возвращает словарь с ключами — именами текущего пространства имен:

>>> locals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
, '__spec__': None, '__annotations__': {}, '__builtins__': , 'name': '__spec__'}

(Заметьте, в пространстве имен появилось имя name, использованное нами выше в качестве переменной в цикле for. И с именем name связано значение, присвоенное ему в цикле последним.)

Наше текущее пространство имен при вводе команд в интерактивном режиме Python — это глобальное пространство имен модуля __main__. Поэтому словарь, возвращаемый функцией globals() и представляющий глобальное пространство имен, совпадает со словарем, возвращаемым locals():


>>> globals()
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
, '__spec__': None, '__annotations__': {}, '__builtins__': , 'name': '__spec__'}

>>> locals() == globals()
True

Мы вернемся к разнице между locals() и globals() позднее. А пока посмотрим внимательно на то, что имеется в глобальном пространстве имен.

Под именем __builtins__ в глобальном пространстве имен имеется модуль builtins, который автоматически импортируется при запуске Python. Этот модуль содержит все встроенные функции и классы, в том числе такие знакомые, как int, float, list, а также все встроенные исключения (exceptions):

>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferEr
ror', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'Conne
ctionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsErr
or', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarni
ng', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'Lookup
Error', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplement
edError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionEr
ror', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'Syn
taxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalE
rror', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarni
ng', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '_', '__build_class__', '__debug__', '__doc__', '__im
port__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray',
'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divm
od', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr& #39;, 'ha
sh', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map',
'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr'
, 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'var
s', 'zip']

В нем есть имена функций dir, eval, locals и globals, которыми мы воспользовались выше так, как будто их имена известны в текущем пространстве имен. Дело в том, что имена, не найденные в глобальном пространстве имен, Python ищет в пространстве имен модуля builtins.

Следующие два вызова по сути одно и то же:

>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'name']
>>> __builtins__.dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'name']

Кстати, любопытно, что не все так называемые встроенные функции Python на самом деле являются функциями; часть из них — классы. Это видно из следующего фрагмента:

>>> for name in dir(__builtins__): print(name, eval(name), eval('type('+name+')'))
...
ArithmeticError
AssertionError
AttributeError
BaseException
BlockingIOError
BrokenPipeError
BufferError
BytesWarning
ChildProcessError
ConnectionAbortedError
ConnectionError
ConnectionRefusedError
ConnectionResetError
DeprecationWarning
EOFError
Ellipsis Ellipsis
EnvironmentError
Exception
False False
FileExistsError
FileNotFoundError
FloatingPointError
FutureWarning
GeneratorExit
IOError
ImportError
ImportWarning
IndentationError
IndexError
InterruptedError
IsADirectoryError
KeyError
KeyboardInterrupt
LookupError
MemoryError
ModuleNotFoundError
NameError
None None
NotADirectoryError
NotImplemented NotImplemented
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
PermissionError
ProcessLookupError
RecursionError
ReferenceError
ResourceWarning
RuntimeError
RuntimeWarning
StopAsyncIteration
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TimeoutError
True True
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
WindowsError
ZeroDivisionError
__build_class__
__debug__ True
__doc__ None
__import__
__loader__
__name__ __main__
__package__ None
__spec__ None
abs
all
any
ascii
bin
bool
bytearray
bytes
callable
chr
classmethod
compile
complex
copyright Copyright (c) 2001-2017 Python Software Foundation.
All Rights Reserved.

Copyright (c) 2000 BeOpen.com.
All Rights Reserved.

Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.

Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved.
credits Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development. See www.python.org for more information.
delattr
dict
dir
divmod
enumerate
eval
exec
exit Use exit() or Ctrl-Z plus Return to exit
filter
float
format
frozenset
getattr
globals
hasattr
hash
help Type help() for interactive help, or help(object) for help about object.
hex
id
input
int
isinstance
issubclass
iter
len
license Type license() to see the full license text
list
locals
map
max
memoryview
min
next
object
oct
open
ord
pow
print
property
quit Use quit() or Ctrl-Z plus Return to exit
range
repr
reversed
round
set
setattr
slice
sorted
staticmethod
str
sum
super
tuple
type
vars
zip

Так, например, eval, any и all являются builtin_function_or_method, а вот filter, map и range являются экземплярами класса type, то есть, классами. (Да ведь это итераторы!)

Следующая попытка разрешить имя pi не удается, потому что это имя не определено в глобальном пространстве имен и не определено в модуле builtins:

>>> pi
Traceback (most recent call last):
File "", line 1, in
NameError: name 'pi' is not defined

Оно определено в модуле math. Импортируем этот модуль и проверим, что изменилось в текущем пространстве имен:

>>> import math
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'math', 'name']

В текущем пространстве имен появилось имя math. Это имя указывает на модуль math:

>>> math

В котором есть много интересного:

>>> dir(math)
['__doc__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'ata
nh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fm
od', 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log',
'log10', 'log1p', 'log2', 'modf', 'nan', 'pi',  9;pow', 'radians', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau', 'trunc']

В том числе, интересующее нас имя pi, с которым связано число пи:

>>> math.pi
3.141592653589793

Мы даже можем его переопределить (хотя это хулиганство):

>>> math.pi = 123.123
>>> math.pi
123.123

Вернемся теперь к вопросу о локальном пространстве имен. Чтобы функция locals() вернула словарь для локального пространства имен, нужно вызвать ее внутри нашей собственной функции, где текущее простраство имен — локальное пространство имен этой функции.

>>> def loc():
... x = 1
... y = 2
... print(locals() == globals())
... print(locals())
... print(globals())
...
>>> loc()
False
{'y': 2, 'x': 1}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
, '__spec__': None, '__annotations__': {}, '__builtins__': , 'name': '__spec__', 'math': <
module 'math' (built-in)>, 'loc': }

Теперь разница между locals() и globals() очевидна.

А в глобальном пространстве имен появилось имя loc, указывающее на определенную нами функцию. Вызовем ее по-другому:

>>> globals()['loc']()
False
{'y': 2, 'x': 1}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
, '__spec__': None, '__annotations__': {}, '__builtins__': , 'name': '__spec__', 'math': <
module 'math' (built-in)>, 'loc': }

Можно вызвать и так (ведь на уровне модуля глобальное и локальное пространства имен совпадают):

>>> locals()['loc']()
False
{'y': 2, 'x': 1}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
, '__spec__': None, '__annotations__': {}, '__builtins__': , 'name': '__spec__', 'math': <
module 'math' (built-in)>, 'loc': }

А как поживает число пи в модуле math?

>>> locals()['math'].pi
123.123

Прекратим это безобразие и, пожалуй, закончим на сегодня:

>>> quit()

C:_dev>

Автор: Andrei Trofimov
Дата публикации: 2017-11-30T15:02:00.000+10:00

Какой язык нужно учить, чтобы зарабатывать сейчас больше

Какой язык нужно учить, чтобы зарабатывать сейчас больше

Конечно же все знают, что сотрудники практически любой компании хорошо владеющие иностранными языками и ценятся начальством больше, да и заработать могут поболее своих коллег — это не секрет. В связи с этим холдинг РБК недавно заказал популярному рекрутинг-ресурсу HeadHunter.ru провести исследование о том как знание иностранных языков повышает зарплатные ожидания у соискателей и ниже для читателей будут даны наиболее важная информация по этой теме.

Django. Отображение фотографий на HTML странице (часть 11)

Добавим теперь фотографии домов, для этого расширим модель. В файле models.py напишем:

photo = models.ImageField(«фотография», upload_to=»houses/photos», default=»», blank=True)

Мы создали поле house_photo, в котором будет храниться ссылка на изображение дома.

default =»» — значение по умолчанию, это пустая строка.
blank=True – говорит, что можно добавлять дом без фотографии.
upload_to=»houses/photos» — путь где будут храниться фотографии

Нажмем Ctrl+Alt+R – создадим миграцию

makemigrations houses
migrate houses

Возможно вы получите следующие ошибки

ERRORS:
houses.House.house_photo: (fields.E210) Cannot use ImageField because Pillow is not installed.
HINT: Get Pillow at https://pypi.python.org/pypi/Pillow or run command:
«pip install Pillow».

Для выполнения следующей миграции без ошибок, нам нужно установить библиотеку Pillow.
Pillow — это библиотека для работы с изображениями.

Выполним:

pip install Pillow

И снова мы можем увидеть следующие ошибки:

pip install pillow failed with error code 1
error for pip install Pillow on Ubuntu virtualenv
failed building wheel for Pillow

Для их исправления нужно выполнить следующие команды

sudo apt-get install python-dev
sudo apt-get install python3-dev
sudo apt-get install libjpeg8-dev zlib1g-dev

Теперь снова выполним команду и в этот раз должно все получиться:

pip install Pillow

Collecting Pillow
Using cached Pillow-3.2.0.zip
Building wheels for collected packages: Pillow
Running setup.py bdist_wheel for Pillow … done
Stored in directory: /home/vlad/.cache/pip/wheels/88/2d/ce/3ff4ae4e2b8600d1bde1cbde5dfcc6d8770222c38348fe9139
Successfully built Pillow
Installing collected packages: Pillow
Successfully installed Pillow-3.2.0

Снова выполним миграцию:

python manage.py makemigrations houses
python manage.py migrate houses

Теперь перейдем в settings.py и включим поддержку медиафайлов. Тоесть файлы, которые будем добавлять мы или наши клиенты через сайт.

Добавим переменную MEDIA_ROOT, которой присвоим «media»

os.path.join(BASE_DIR, «media»)

, то есть мы будем хранить файлы в папке «media», которая будет находится в папке проекта BASE_DIR

Также добавим переменную MEDIA_URL, которой присвоим строку «/media/»

MEDIA_URL — это адрес по которому пользователь сможет получить доступ к нашим медиа файлам.

Теперь перейдем в файл urls.py и импортируем в него функцию static

from django.conf.urls.static import static

А также импортируем настройки проекта:

from django.conf import settings

После, к urlpatterns прибавим функцию static()
Первым аргументом укажем settings.MEDIA_URL, а вторым именованный document_root=settings.MEDIA_ROOT

urlpatterns = [] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Переходим в админку, выбираем дом бюджет, теперь мы видим, что появилось новое поле Фотография, которое в отличии от других полей не выделено жирным, то есть оно не обязательно для заполнения. Добавим фото и нажмем сохранить. Фотография загрузится на сервер в папку houses/photos

Теперь в папке проекта должна появится папка media, внутри которой houses и photos, в соответствии со структурой upload_to

Выведем теперь фотографию на сайт. Откроем шаблон houses_list.html и напишем:

if, затем нажмем TAB, чтобы быстро создать инструкцию

{% if house.house_photo %}

{% endif %}

А в теле инструкции напишем:

img, затем нажмем TAB, чтобы быстро создать конструкцию

В скобках {{ }} добавим house.house_photo.url и house.house_name

Разберем код:

Мы добавили условие, если у дома есть фотография house.house_photo, то подставить в атрибут src=»» ссылку на неё {{ house.house_photo.url }}, а в атрибут alt=»» имя дома {{ house.house_name }}

Откроем сайт и посмотрим, фотография Бюджетного дома — теперь выводится.

Отлично!

Автор: Vladimir Semenovich

Django. Наполнение страницы данными (часть 10)

Наполним страницу данными, вернемся в views.py и импортируем модуль house

from .models import House

А затем внутри представления напишем:

houses = House.objects.all()

House.objects.all() — этой строкой мы создаем запрос к нашей базе данных с помощью ORM.
objects.all() — запрос на получение всех объектов

Теперь в переменной houses содержаться все дома, которые мы добавили через админку. Мы снова обошлись без SQL запросов к базе данных, что очень упрощает разработку.

Передадим дома в наш шаблон, для этого добавим в функцию render(), третий параметр словарь, в котором напишем {“houses”: houses}, теперь в нашем шаблоне доступны созданные нами объекты.

Перейдем в html файл, т.к. мы связали шаблон с представлениями через render(), то теперь можно кликнуть по значку напротив объявления функции.

Теперь в houses_list.html нам нужно вывести дома через переменную hoses, которую мы передали в шаблон. Для этого нужно воспользоваться языком шаблонов Django.
Язык шаблонов Django — это такой упрощенный язык, с помощью которого можно обращаться к python объектам внутри html файла, а также реализовывать простейшую логику вроде циклов и условий.

Напишем for и нажмем TAB, Pycharm создаст для нас конструкцию for и поместит в нее объект houses

Конструкция for заключается в фигурные скобки с % и имеет окончание {% endfor %}
Внутри конструкции нам доступен объект house, который отвечает за один единственный дом.

Напишем:

div>h2+div*2

и нажмем TAB, чтобы Pycharm быстро создал несколько HTML тэгов.

Добавим в двойных фигурных скобках:

{{ house.name }}
{{ house.price }}
{{ house.description }}

{% … %} — если фигурные скобки с % отвечают за синтаксические конструкции, как например в for, то с помощью двойных фигурных скобок {{ … }}, мы можем обращаться к Python объектам, в нашем случае к объекту house и сейчас мы выводим данные по нашему объекту в HTML.

Откроем сайт и обновим страницу

Отлично!

Автор: Vladimir Semenovich

Django. Отображение данных на сайте (часть 9)

Для того чтобы показать наши дома на сайте, откроем views.py в нем мы будем хранить так называемые представления — это специальная функция, которая будет возвращать html-страницу в браузере.

В файл views.py добавим функцию houses_list, в которой зададим аргумент request.

def houses_list(request):
pass

Request — это запрос вашего посетителя, когда посетитель заходит на страницу сайта, то браузер формирует специальный запрос web-серверу, Django этот запрос обрабатывает и помещает его в специальный объект request. Затем Django вызывает, какое-то представления, например houses_list и передает в его запрос request, а после представление помещает html-страницу обратно в браузер.

Чтобы вернуть html-страницу ее нужно создать.

Добавим в папку houses, новую папку templates.
Templates — это простая папка, а не python пакет в ней __init__.py файл не нужен. В нутри templates добавим еще одну папку houses, как и имя нашего приложения, а уже в ней создадим houses_list.html и добавим текст в

«Дом у моря»

Затем вернемся в views.py

views.py

Как вы заметили имя представления article_list(request) совпадает с именем шаблона houses_list.html, который мы создали. Так делать не обязательно, но это хорошая практика, которая проще позволяет ориентироваться в коде.

Добавим в представление:

def houses_list(request):
return render(request, “houses/houses_list.html”)

Тоесть мы в функции houses_list, возвращаем отрендеренный шаблон houses_list.html

Дополнительно в функцию houses_list мы передаем запрос посетителя request

Теперь нам нужно связать нашу функцию представления с каким-то URL.

Перейдем в urls.py и импортируем в него наше представление:

from houses.views import houses_list

А в список urlpatterns скопируем строку из комментария и заменим views.home на houses_list

Первый параметр в функции url — это регулярное выражение, которое отвечает за путь на сайте

^ — это начало адреса
$ — это конец адреса
r’^s’ — все выражение соответствует главной странице

Когда посетитель перейдет на главную страницу сайта, Django сопоставит путь с регулярным выражением, т.к. путь будет соответствовать этой записи r’^s’, то Django запустит представление houses_list,

которое вернет отрендеренную html-страницу

Теперь откроем браузер и увидим нашу пустую страницу с заголовком дом у моря

Автор: Vladimir Semenovich