Meyer's substitution uniform access principle
Атрибутите на един обект трябва да бъдат достъпвани през хомогенна нотация, която не издава дали те се изчисляват или са записани.
Liskov substitution principle:
Let q(x) be a property provable about objects x of type T. Then q(y) should be true for objects y of type S where S is a subtype of T.
Ако S е подтип на T, и q(t) свойство, което важи за всеки обект от тип T, тогава q(t) трябва да важи за всеки обект от тип S.
def func(x): return x + 1 def test_answer(): assert func(3) == 5
Къде е магията?
=========================== test session starts ============================ python: platform linux2 -- Python 2.6.2 -- pytest-1.1.0 test object 1: test_sample.py test_sample.py F ================================= FAILURES ================================= _______________________________ test_answer ________________________________ def test_answer(): > assert func(3) == 5 E assert 4 == 5 E + where 4 = func(3) test_sample.py:6: AssertionError ========================= 1 failed in 0.08 seconds =========================
from dejavu import Unit,UnitProperty,storage import os import dejavu class Zoo(Unit): Name = UnitProperty() Size = UnitProperty(int) def total_legs(self): return sum([x.Legs for x in self.Animal()]) # вместо Пайтън да ви сметне сумата, този ред # генерира SQL код и го пуска към базата данни
from DbC import DbC class Test(metaclass = DbC): @invar(x >= 0) def __init__(self, x): self.x = x @pre(x >= 0) @post(res == x + 1) def foo(self, x): result = x + self.x self.x -= 2 return result @staticmethod @pre(len(list(map(lambda x: x + 2, filter(lambda y: y == 0, z + [0])))) == 1) def bar(z): pass t = Test(1) t.foo(3) Test.bar([1, 2, 3])
rom multi import Multi class Bar(metaclass = Multi): def what(self, y : str, z : int, x : str): return 5 def what(self, y : object, z : str, x : str = "abc"): return x def what(self, y : str, z : str, x : str): return x + y + z b = Bar() assert b.what("b", x = "a", z = "c") == "abc" assert b.what(z = "a", y = 8) == "abc" assert b.what(z = "a", x = "b", y = 1) == "b"
Objects are Python’s abstraction for data. All data in a Python program is represented by objects or by relations between objects.
class Person: def __init__(self, name): self.name = name def say_hi(self): print("Hi, I am", self.name)
Обектите отвътре са просто речници. Всеки обект си има специален речник който пази атрибутите му:
>>> goshko = Person('Gospodin Goshko') >>> hasattr(goshko, '__dict__') True >>> goshko.__dict__ {'name': 'Gospodin Goshko'} >>> goshko.__dict__['profession'] = 'Hacker' >>> goshko.profession 'Hacker' >>> goshko.__dict__ {'profession': 'Hacker', 'name': 'Commander Gosh'} >>> goshko.__dict__.clear() >>> goshko.name Traceback (most recent call last): File "", line 1, in AttributeError: 'Person' object has no attribute 'name'
class Ninja: def __init__(self, name, target): self.name = name self.target = target def say_hi(self): print("Ninja!") def kill_target(self): print("Slash ", self.target)
>>> goshko = Person('Gospodin Goshko') >>> goshko.say_hi() Hi, I am Gospodin Goshko >>> type(goshko) <class '__main__.Person'> >>> goshko.__class__ <class '__main__.Person'> >>> goshko.__class__ = Ninja >>> type(goshko)>>> goshko.say_hi() Ninja! >>> goshko.kill_target() Traceback (most recent call last): File " ", line 1, in File " ", line 4, in kill_target AttributeError: 'Ninja' object has no attribute 'target'
object.__new__(cls[, ...]) # class method object.__init__(self[, ...]) object.__del__(self)
__new__ е истинският конструктор на вашите обекти. __init__ е само инициализатор:
class Vector(tuple): def __new__(klass, x, y): return tuple.__new__(klass, (x, y)) def __add__(self, other): if not isinstance(other, Vector): return NotImplemented return Vector(self[0] + other[0], self[1] + other[1])
object.__getattr__(self, name) object.__setattr__(self, name, value) object.__delattr__(self, name) object.__dir__(self)
object.__getattribute__(self, name)
При извикване на obj.name
:
name
не присъства в obj.__dict__
. Ако да - връща се тази стойностobj.__class__
има такъв атрибут в своя __dict__
. Ако да, и той няма метод __get__
, се връщаobj.__dict__
има метод __get__
, то методът obj.__dict__.__get__
се изпълнява със съответните оргументиobject.__get__(self, instance, owner) object.__set__(self, instance, value) object.__delete__(self, instance)
# direct call x.__get__(a) # instance binding on a.x type(a).__dict__['x'].__get__(a, type(a)) # class binding on A.x A.__dict__['x'].__get__(None, A) # super binding # super black magic