„ Програмиране с Python“, ФМИ
Стефан Кънев & Николай Бачийски
12.03.2007г.
Елементарен проблем
world.py:
""" A module for playing with the world. """
def destroy():
"""Destroys the world."""
print "The world was destroyed!"
def save(kind):
"""Saves a kind."""
print "All the", kind, "were saved."
Искаме да ползваме горните функции в много програми, а не искаме да копираме кода във всяка от тях.
Елементарно решение
women.py:
import world
world.save('women')
world.destroy()
animals.py:import world
world.save('animals')
world.destroy()
Работи без проблеми ако трите файла са в една директория.
Чрез модули можем да използваме един и същи код много пъти (code reuse).
Атрибути
- Обектите имат свързани с тях имена, наречени атрибути, които се достъпват чрез оператора
.
(точка) - Нека разгледаме по-подробно
world.destroy()
destroy
е функция и е атрибут на обектаworld
, който пък е модул>>> world
>>>world.destroy
- с вградената функция
dir
можем да видим всички атрибути на обект: >>> dir(world)
['__builtins__', '__doc__', '__file__', '__name__', 'destroy', 'save']
>>> world.__doc__
' A module for playing with the world. '
>>> world.__name__
'world'
Области от имена (1)
- Всяка програма е модул сама по себе си и всички глобални имена, са негови атрибути
- savepoohs.py:
import world
def savePoohs():
world.save('Poohs')
insane = True
print dir()- Ще отпечата:
[<системни атрибути> 'world', 'savePoohs', 'insane']
Области от имена (2)
- В различни модули можем да имаме едни и същи имена
- Всеки модул си има различен набор от имена
import pooh
import piglet
def breakfast():
print "Is it already eleven?"
pooh.breakfast()
piglet.breakfast()
breakfast()
Ако използваме модули няма нужда да се притесняваме, че в няколко програми сме използвали едни и същи имена.
Търсене на атрибути
answer = 42
- в този случай е ясно, че обектът зад името
answer
трябва да се търси по стандартния начин (в разните обхвати) pooh.naivete = 42
- името
naivete
не трябва да се търси в стандартните обхвати, а трябва да се търси в списъка с атрибути на обекта зад иметоpooh
universe.milkyway.earth.europe.bg.beautify()
Модули и обхвати
- Глобалните променливи са на практика модулни променливи. Те са глобални само в рамките на модула, в който се намират.
- mod.py:
bottles = 1
def addBottle():
global bottles
bottles += 1- bottler.py:
import mod
bottles = 5
mod.addBottle()
print bottles, mod.bottles
Използване на модули — import
Чрез вградената фунцкия import
ни дава възможност да ползваме код от външни файлове.
Ето какво се случва, ако изпълним import mod
:
- Намира се файла, в който се намира модула
- Кодът се компилира до байт-код (ако е необходимо)
- Кодът на модула се изпълнява (дефиниции на функции, друг код)
- На името
mod
се присвоява обекта на изпълнения модул
Търсене на файла
import mod
Търси се в:
- текущата директория
- променливата на средата
PYTHONPATH
- системни директории с модули
- директории, описани в
.pth
файлове
Всички по реда на претърсване: списъка sys.path
Модул vs. Програма
- И в двата случая кодът ни се изпълнява
- Искаме ако кодът ни е бил изпълнен директно да тестваме модула си
- Искаме ако кодът ни е бил включен с
import
само да дефинираме фукнциите си - eater.py:
def eat(what):
print what, "was eaten."
if (__name__ == '__main__'):
eat('The world as we know it')$ python eater.py
The world as we know it was eaten.>>> import eater
Пакети от модули
Представете си, че имаме две отделни системи, в които има модул на име game
system1/
game.py
<други модули>
system2/
game.py
<други модули>
Сега напишете система, която използва модулите game
и от двете други:
import game
game.play()
Тук вече имаме малък проблем.
Пакети от модули (2)
Би било много удобно ако можехме да разделим двата модула game
в отделни пакети:
import system1.game
import system2.game
system1.game.play()
system2.game.play()
Това е възможно при няколко условия:
- директориите system1 и system2 са някъде из пътя за търсене на python
- във всяка от тях има файл с име
__init__.py
При import на по-сложно име се извършва следното:
- намира се поредната компонента от пътя (разделени с точки)
- ако има съответстващ файл — включва се
- ако е директория — изпълнява се
__init__.py
в нея
Пакети от модули (3)
С пакети от модули можем с едни замах да import-нем много модули:
forest/pooh.py:
name = 'Pooh'
forest/piglet.py:
name = 'Piglet'
forest/__init__.py:
import pooh
import piglet
user.py: import forest
print forest.pooh.name
print forest.piglet.name
import
import mod
— намира се модула и обектът му се присвоява на иметоmod
sys = '/usr/src/sys'
import os
def listByExt(path, ext):
return [d for d in os.listdir(path) if d.endswith('.'+ext)]
# искаме да отпечатаме sys.path
import sys
print sys.path
# сега да видим всички питонски файлове в /usr/src/sys
print listByExt(sys, 'py')
# опс:
TypeError: coercing to Unicode: need string or buffer, module found
import as
import sys as sysmod
print sysmod.path Почти същото е като: import sys
sysmod = sys
del sys
sysmod.path
само че ще загубим старата стойност на sys
from mod import names
Понякога е досадно да извикваме всеки път цялото име на накой обект, като universe.milkyway.earth.europe.bg.beautify()
from universe.milkyway.earth.europe.bg import beautify
beautify()
Или даже:
from universe.milkyway.earth.europe.bg import beautify as b
b()
from mod import *
Хубаво ли ви е така:
from mod import a,b,c,d,e,f,g,h,i,j,k,l
И на мен. Затова Python ни позволява да внесем в нашия модул всички имена от някой друг: from mod import *
- Имената от типа
_име
не се внасят - Имената от типа
__име__
не се внасят - Ако в
mod
има списък с име__all__
, то се внасят само имената съдържащи се в него
Още разни модулни неща
- Съществува модул
__builtin__
, който съдържа всички вградени функции и други имена:import __builtin__
__builtin__.dir = abs
print dir(-3) - модулите се импортират само веднъж:
За презареждане трябва да се ползва>>> import world
>>> world.save('babas')
All the babas were saved.
>>> world.save = 5
>>> import world
>>> world.save
5reload()
:>>> world.save
5
>>> reload(world)
>>> world.save
Няма коментари:
Публикуване на коментар