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