Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6507 
 Linux Kernel 2.6...5279 
 Trees...1115 
 Максвелл 3...1050 
 William Gropp...986 
 Go Web ...957 
 Ethreal 3...929 
 Ethreal 4...915 
 Gary V.Vaughan-> Libtool...912 
 Ext4 FS...901 
 Clickhouse...900 
 Rodriguez 6...897 
 Ethreal 1...896 
 Steve Pate 1...884 
 C++ Patterns 3...860 
 Assembler...851 
 Ulrich Drepper...844 
 DevFS...786 
 MySQL & PosgreSQL...769 
 Стивенс 9...756 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

Python Tutorial 4


9. Классы

Классы в питоне - это смесь 2-х механизмов , взятых от C++ и Modula-3. Основные фичи - множественная наследование , перегрузка базовых методов .

Все члены класса , включая данные , имеют тип public, и все функции virtual. Нет специальных конструкторов или деструкторов . Классы сами по себе обьекты , в питоне все типы данных - обьекты. Встроенные операторы (напр,арифметические) имеют специфический синтаксис и могут быть переопределены для обьектов класса .

Обьекты индивидуальны . У одного обьекта может быть несколько имен (алиасов). Алиас - в некотором смысле указатель на обьект .

namespace - пространство имен обьектов . Примеры namespaces : встроенные имена (такие как функция abs()); глобальные имена модуля; локальные переменные функций . Между этими namespaces нет абсолютно никакой связи - например 2 разных модуля могут иметь 2 разных функции с одни и тем же названием``maximize''.

Термин attribute справедлив для любого имени , следующего за точкой - например в выражении z.real, real есть атрибут обьекта z. Ссылка на имя в модуле - ссылка на атрибут : в выражении modname.funcname, modname есть модуль и funcname - его атрибут .

Атрибуты могут быть на чтение или запись . Во втором случае возможна операция присваивания . Для атрибута модуля можно написать : "modname.the_answer = 42". Атрибут модуля может быть удален с помощью операции del . Например : "del modname.the_answer" .

Разные Namespaces создаются в разные моменты времени . Например , namespace для built-in имен создается в момент запуска интерпретатора Python . namespace для модуля создается в момент , когда читается его определение . Исполняемый код также имеет собственный глобальный namespace.

Локальный namespace для функции создается при ее вызове и удаляется при выходе . Хотя удаляется - это сказано круто , правильнее сказать - как-бы забывается и позднее будет ликвидирован сборщиком мусора .

scope - область видимости , в которой доступен namespace.

В любой момент времени доступны сразу несколько scopes : innermost scope - включает локальные имена и функции ; middle scope - глобальные имена текущего модуля; outermost scope - built-in идентификаторы .

Если имя глобально , оно лежит в middle scope . Все переменные за пределами innermost scope только на чтение .

Функция ищет глобальные переменные внутри своего модуля .

Операция присваивания в питоне выполняется всегда в innermost scope. Присваивание - это не копирование данных , это просто привязка имен к обьектам . То же справедливо и для удаления - операция "del x" удаляет привязку x .


9.3.1 Инициализация классов

Простейшая форма определения класса :

class ClassName:
     <statement-1>
     .
     .
     .
     <statement-N>
 

Класс можно определить в любом месте - хоть внутри функции .

Внутри класса идут определения функций .

Вместе с классом создается новый namespace .

Если внутри класса все определения корректны , создается обьект класса .


9.3.2 Обьект класса

Обьект класса может быть ссылкой или инстансом .

Ссылка стандартна для питона : obj.name. Например :

class MyClass:
     "A simple example class"
     i = 12345
     def f(self):
         return 'hello world'
 

После чего можно обратиться по ссылке MyClass.i и MyClass.f . К атрибутам класса можно применить операцию присваивания .

При создании инстанса используется функциональная нотация . При этом обьект класса есть параметризованная функция , которая возвращает обьект класса :

x = MyClass()
 

При этом создается пустой обьект . Класс может иметь специальный метод __init__():

    def __init__(self):
         self.data = []
 

При создании инстанса метод __init__() вызывается автоматом .

x = MyClass()
 

__init__() может иметь аргументы :

>>> class Complex:
 ...     def __init__(self, realpart, imagpart):
 ...         self.r = realpart
 ...         self.i = imagpart
 ...
 >>> x = Complex(3.0, -4.5)
 >>> x.r, x.i
 (3.0, -4.5)
 


9.3.3 Инстанс - обьекты .

В классах возможны 2 типа атрибутов - первый : data attributes. Это примерно то же самое , что и ``data members'' в C++. Например , если x - инстанс MyClass , следующий код распечатает 16:

x.counter = 1
 while x.counter < 10:
     x.counter = x.counter * 2
 print x.counter
 del x.counter
 

Второй тип атрибутов,который понимают инстансы,называется methods.

Любая функция класса может быть атрибутом-методом для инстанса . Например, x.f верная ссылка на метод, поскольку MyClass.f - функция, но x.i неверно, поскольку MyClass.i не существует. Но x.f - это не то же самое , что и MyClass.f -- это метод, а не функция.


9.3.4 Методы

Вызов метода :

x.f()
 

В нашем примере будет возвращена строка 'hello world'. Аналогично :

xf = x.f
 while True:
     print xf()
 

Внутри класса можно сделать ссылку на функцию , которая определена вне класса :

# Function defined outside the class
 def f1(self, x, y):
     return min(x, x+y)
 
 class C:
     f = f1
     def g(self):
         return 'hello world'
     h = g
 

Методы могут вызывать другие методы :

class Bag:
     def __init__(self):
         self.data = []
     def add(self, x):
         self.data.append(x)
     def addtwice(self, x):
         self.add(x)
         self.add(x)
 

Методы могут ссылаться на глобальные имена .


9.5 Наследование

Синтаксис для определения производного класса :

class DerivedClassName(BaseClassName):
     <statement-1>
     .
     .
     .
     <statement-N>
 

Должно быть определено имя базового класса BaseClassName. Можно также ссылаться на базовый класс из другого модуля .

class DerivedClassName(modname.BaseClassName):
 

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

Производный класс может перегружать методы базового класса .

Напрямую базовый класс можно вызвать так :"BaseClassName.methodname(self, arguments)".


9.5.1 Множественное наследование

Определение класса с множественным наследованием :

class DerivedClassName(Base1, Base2, Base3):
     <statement-1>
     .
     .
     .
     <statement-N>
 

При этом порядок наследования следующий : если атрибут не найден в DerivedClassName, он ищется в Base1, затем (рекурсивно) в базовом классе Base1, затем в Base2, и так далее . Для питона известна проблема , когда класс унаследован от 2-х классов , имеющих общий базовый класс .


9.6 Private переменные

Поддержка этого типа переменных специфична для питона . Такая переменная должна быть определена с префиксом _classname__spam, где classname имя класса. Тип private может быть как у данных , так и у методов .

Для создания типа , аналогичного типу``struct'' из C , можно использовать пустой класс :

class Employee:
     pass
 
 john = Employee() # Create an empty employee record
 
 # Fill the fields of the record
 john.name = 'John Doe'
 john.dept = 'computer lab'
 john.salary = 1000
 


9.8 Exceptions

Имеются 2 новых формы исключений :

raise Class, instance
 
 raise instance
 

В первом случае , instance должен быть инстансом Class или класса , производного от него . Второй вариант есть аналог для :

raise instance.__class__, instance
 

В следующем примере будет распечатано B, C, D :

class B:
     pass
 class C(B):
     pass
 class D(C):
     pass
 
 for c in [B, C, D]:
     try:
         raise c()
     except D:
         print "D"
     except C:
         print "C"
     except B:
         print "B"
 

Если поставить первым "except B" , будет напечатано B, B, B .


9.9 Итераторы

В любом контейнере можно использовать цикл с использованием for :

for element in [1, 2, 3]:
     print element
 for element in (1, 2, 3):
     print element
 for key in {'one':1, 'two':2}:
     print key
 for char in "123":
     print char
 for line in open("myfile.txt"):
     print line
 

У контейнера имеется 2 метода - iter() и next() . Их использование показано в примере :

>>> s = 'abc'
 >>> it = iter(s)
 >>> it
 <iterator object at 0x00A1DB50>
 >>> it.next()
 'a'
 >>> it.next()
 'b'
 >>> it.next()
 'c'
 >>> it.next()
 
 Traceback (most recent call last):
   File "<pyshell#6>", line 1, in -toplevel-
     it.next()
 StopIteration
 

Использование итераторов в классе :

class Reverse:
     "Iterator for looping over a sequence backwards"
     def __init__(self, data):
         self.data = data
         self.index = len(data)
     def __iter__(self):
         return self
     def next(self):
         if self.index == 0:
             raise StopIteration
         self.index = self.index - 1
         return self.data[self.index]
 
 >>> for char in Reverse('spam'):
 ...     print char
 ...
 m
 a
 p
 s
 


9.10 Генераторы

Генераторы - средство для создания итераторов . Используется ключевое слово yield , которое заменяет return :

def reverse(data):
     for index in range(len(data)-1, -1, -1):
         yield data[index]
 
 >>> for char in reverse('golf'):
 ...     print char
 ...
 f
 l
 o
 g
 

Генератор может быть выражением :

>>> sum(i*i for i in range(10))                 # sum of squares
 285
 
 >>> xvec = [10, 20, 30]
 >>> yvec = [7, 5, 3]
 >>> sum(x*y for x,y in zip(xvec, yvec))         # dot product
 260
 
 >>> from math import pi, sin
 >>> sine_table = dict((x, sin(x*pi/180)) for x in range(0, 91))
 
 >>> unique_words = set(word  for line in page  for word in line.split())
 
 >>> valedictorian = max((student.gpa, student.name) for student in graduates)
 
 >>> data = 'golf'
 >>> list(data[i] for i in range(len(data)-1,-1,-1))
 ['f', 'l', 'o', 'g']
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье