Показаны сообщения с ярлыком Python. Показать все сообщения
Показаны сообщения с ярлыком Python. Показать все сообщения

понедельник, 6 марта 2017 г.

Шпаргалка по слотам (object.__slots__)

Для чего же нужны __slots__?
Снизить потребление памяти, экземпляром класса, путем ограничения количества поддерживаемых атрибутов.



При использовании __slots__, атрибут __dict__ будет недоступен. Если нужно иметь __dict__, его нужно добавить в __slots__, это будет означать что динамические атрибуты будут работать, тоесть добавляться в словарь __dict__.
Пример:


class A(object):
    """Класс со слотами.

    """
    __slots__ = ('a', 'b', 'c')



Соответственно при попытке доступа в __dict__ получим исключение:


In [1]: a = A()

In [2]: a.__dict__
---------------------------------------------------------
AttributeError        Traceback (most recent call last)
 in ()
----> 1 a.__dict__

AttributeError: 'A' object has no attribute '__dict__'

In [3]: dir(a)
Out[3]: 
['__class__',
 '__delattr__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__slots__',
 '__str__',
 '__subclasshook__',
 'a',
 'b',
 'c']



Если добавить __dict__ в слоты

class A(object):
    """Класс со слотами.

    """
    __slots__ = ('a', 'b', 'c', '__dict__')


Тогда:

In [4]: a = A()

In [5]: a.__dict__
Out[5]: {}

In [6]: dir(a)
Out[6]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__slots__',
 '__str__',
 '__subclasshook__',
 'a',
 'b',
 'c']



Не имея атрибута __weakref__, экземпляры классов со __slots__ не поддерживают слабые ссылки на себя. Для поддержки слабых ссылок нужно добавить в перечень атрибутов __weakref__ по тому же принципу как и __dict__.

При наследовании от класса со слотами если не объявлены слоты, будет доступен __dict__ соответственно и динамические аттрибуты будут работать. При этом поведение атрибутов объявленых в слотах родительского класса не пеняется.


class A(object):
    """Класс со слотами.

    """
    __slots__ = ('a', 'b', 'c')


class B(A):
    """Класс без слотов, но наследующий класс со слотами.

    """
    pass

In [7]: b = B()

In [8]: dir(b)
Out[8]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__slots__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'a',
 'b',
 'c']

In [9]: b.__dict__
Out[9]: {}

In [10]: b.a
---------------------------------------------------------
AttributeError        Traceback (most recent call last)
 in ()
----> 1 b.a

AttributeError: a




При наследовании от класса не имеющего __slots__, родителем будет создан __dict__


class C(object):
    """Класс без слотов.

    """
    pass


class D(C):
    """Класс со слотами, но наследующий класс без слотов.

    """
    __slots__ = ('q', 'w', 'e')


In [11]: c = C()

In [12]: d = D()

In [13]: c.__dict__
Out[13]: {}

In [14]: d.__dict__
Out[14]: {}

In [15]: d.__slots__
Out[15]: ('q', 'w', 'e')

In [16]: dir(c)
Out[16]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

In [17]: dir(d)
Out[17]: 
['__class__',
 '__delattr__',
 '__dict__',
 '__doc__',
 '__format__',
 '__getattribute__',
 '__hash__',
 '__init__',
 '__module__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__slots__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'e',
 'q',
 'w']


И еще, нельзя определить __slots__ для классов наследующихся от встроенных типов переменной длины, например long, str и tuple. Точнее определить можно, но ненужно :) так как получите исключение TypeError
Читать дальше...

вторник, 15 марта 2011 г.

Простое сравнение языков программирования Python PHP

После прочтения mocksoul.livejournal.com решил сравнить PHP и Python на том же коде.

Итак поехали:


IO Test: запись в файл.
test.php
<?php

$fp = fopen('/tmp/iotest', 'wb');
for ($i = 0; $i < 1000000; $i++)
{
fwrite($fp, $i);
}
fclose($fp);

?>

test.py
#!/usr/bin/env python

f = open('/tmp/iotest','wb');
for i in xrange(1000000):
f.write(str(i));
f.close()

Результаты (IO)
php 39.378192 сек.
python 8.538952 сек.
Честно говоря я даже растерялся

Hash Test: создание массивов
test.php
<?php
for ($i = 0; $i < 6000; $i++)
{
$x = array();
for ($j = 0; $j < 1000; $j++)
{
$x[$j] = $i;
$x[$j];
}
}
?>

test.py
#!/usr/bin/env python
for i in range(6000):
x={}
for j in range(1000):
x[j]=i
x[j]

Результаты (Hashing)
php 10.914512 сек.
python 11.578563 сек.

Console Test: Вывод на консоль. В этом тесте я уменьшил число
test.php
<?php
for ($i = 0; $i < 100000; $i++)
{
echo $i . "\n";
}
?>

test.py
#!/usr/bin/env python

for x in xrange(100000):
print x

Результаты (Console)
php 10.52952 сек.
python 10.96296 сек.
List Test: Заполнение списков.
test.php
<?php
for ($i = 0; $i < 3000; $i++)
{
$v = array('a', 'b', 'c', 'd', 'e', 'f', 'g');
for ($j = 0; $j < 1000; $j++)
{
array_push($v, $j);
$v[$j];
}
}
?>

test.py
#!/usr/bin/python
for i in range(3000):
v=['a','b','c','d','e','f','g']
for j in range(1000):
v.append(j)
v[j]

Результаты (List)
php 11.84869 сек.
python 6.69352 сек.
No Test. Просто ничего не делаем.
test.php
<?php

?>

test.py
#!/usr/bin/env python

Результаты (No Test)
php 0.020854 сек.
python 0.000003 сек.
Speed Test: Скорость итераций.
test.php
<?php
for ($i = 0; $i < 20000000; $i++)
{

}
?>

test.py
#!/usr/bin/env python
for x in xrange(20000000):
pass

Результаты (Speed)
php 11.82229 сек.
python 9.83335 сек.

Версии ПО:
PHP 5.3.2
Python 2.6.5
Версия ОС:
Linux 2.6.32-30-generic #59-Ubuntu SMP Tue Mar 1 21:30:21 UTC 2011 i686 GNU/Linux

Получился довольно интересный результат 4 из 6 тестов Python обошел PHP :)

При копировании материалов
ссылка на источник обязательна!


Читать дальше...