11

Разница между старыми и новыми классами в Python?

14

Какова разница между старыми и новыми стилями классов в Python? Когда следует использовать один из них, а когда - другой?

4 ответ(ов)

3

С точки зрения объявления:

Новые классы (new-style classes) наследуются от object или от другого нового класса.

class NewStyleClass(object):
    pass

class AnotherNewStyleClass(NewStyleClass):
    pass

Старые классы (old-style classes) этого не делают.

class OldStyleClass():
    pass

Примечание для Python 3:

Python 3 не поддерживает старые классы, поэтому любая форма, указанная выше, приводит к созданию нового класса (new-style class).

0

В старых классах немного быстрее происходит поиск атрибутов. Это, как правило, не имеет большого значения, но может быть полезно в производительном коде на Python 2.x:

In [3]: class A:
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...:

In [4]: class B(object):
   ...:     def __init__(self):
   ...:         self.a = 'hi there'
   ...:

In [6]: aobj = A()
In [7]: bobj = B()

In [8]: %timeit aobj.a
10000000 loops, best of 3: 78.7 ns per loop

In [10]: %timeit bobj.a
10000000 loops, best of 3: 86.9 ns per loop

Как видно из результатов тестирования, доступ к атрибуту объекта класса A (старый стиль) происходит быстрее, чем у объекта класса B (новый стиль). Для большинства случаев это несущественно, однако в скоростных критичных приложениях на Python 2.x стоит иметь это в виду.

0

Вопрос: Как влияет наследование от объекта на поведение классов в Python?

Ответ: Вот очень практическое различие между старыми и новыми классами в Python. Единственное различие между двумя версиями приведенного ниже кода заключается в том, что во второй версии класс Person наследуется от object. В остальном обе версии идентичны, но дают разные результаты:

  1. Старые классы (Old-style classes)

    class Person():
        _names_cache = {}
        def __init__(self, name):
            self.name = name
        def __new__(cls, name):
            return cls._names_cache.setdefault(name, object.__new__(cls, name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print(ahmed1 is ahmed2)
    print(ahmed1)
    print(ahmed2)
    
    >>> False
    <__main__.Person instance at 0xb74acf8c>
    <__main__.Person instance at 0xb74ac6cc>
    
  2. Новые классы (New-style classes)

    class Person(object):
        _names_cache = {}
        def __init__(self, name):
            self.name = name
        def __new__(cls, name):
            return cls._names_cache.setdefault(name, object.__new__(cls, name))
    
    ahmed1 = Person("Ahmed")
    ahmed2 = Person("Ahmed")
    print(ahmed1 is ahmed2)
    print(ahmed1)
    print(ahmed2)
    
    >>> True
    <__main__.Person object at 0xb74ac66c>
    

Как видно из вывода, в старых классах экземпляры с одинаковыми именами не являются одним и тем же объектом (результат False), в то время как в новых классах экземпляры с одинаковыми именами — это тот же объект (результат True). Это связано с тем, что новые классы (New-style classes), наследуемые от object, изменяют поведение механизма создания объектов в Python.

0

В новых классах стилей можно использовать super(Foo, self), где Foo — это класс, а self — это экземпляр.

Функция super(type[, object-or-type]) возвращает прокси-объект, который перенаправляет вызовы методов к родительскому или смежному классу типа. Это полезно для доступа к унаследованным методам, которые были переопределены в классе. Порядок поиска такой же, как и в getattr(), за исключением того, что сам тип пропускается.

В Python 3.x вы можете просто использовать super() внутри класса без каких-либо параметров.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь