class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def coords(self):
return [self.x, self.y, self.z]
def length(self):
return sum(c ** 2 for c in self.coords()) ** 0.5
>>> v = Vector(1.0, 2.0, 3.0)
>>> print(v.coords())
[1.0, 2.0, 3.0]
>>> print(v.length())
3.74165738677
class
, последван от блокself
- reference към обекта, на който ги извикватеself
class Spam:
def __init__(self, arg):
self.stored = arg
>>> spam = Spam(42)
>>> print(spam.stored)
42
>>> spam.stored = 60
>>> print(spam.stored)
60
>>> spam.foo = 10
>>> print(spam.foo)
10
По този начин може да използвате класовете като структури:
class Student: pass
mityo = Student()
mityo.name = "Mityo the Python"
mityo.age = 22
mityo.faculty_number = 42424
self
.обект.метод(аргументи)
, така и с клас.метод(обект, аргументи)
class Person:
def __init__(self, name):
self.name = name
def greet(self, somebody):
print("Hello {0}, I'm {1}!".format(somebody, self.name))
>>> mityo = Person("Mityo the Python")
>>> mityo.greet('Stefan')
Hello Stefan, I'm Mityo the Python!
>>> Person.greet(mityo, 'Stefan')
Hello Stefan, I'm Mityo the Python!
Интересен страничен (или не толкова страничен) ефект е следното:
>>> person = Person("Mityo the Python")
>>> greet_someone = person.greet
>>> greet_someone("Stefan")
Hello Stefan, I'm Mityo the Python!
Обаче:
>>> greeter = Person.greet
>>> greeter(mityo, "Stefan")
Hello Stefan, I'm Mityo the Python!
При статичните методи положението е малко странно:
class Person:
people = []
def register(name):
Person.people.append(name)
print(len(Person.people), "people are registered now")
register = staticmethod(register)
>>> Person.register("Mityo the Python")
1 people are registered now
>>> Person.register("Pooh")
2 people are registered now
Има по-хубав синтаксис, но ще ви го покажем, като говорим за декоратори.
В Python има "класови" методи, които вземат класът на който са извикани като първи аргумент. Понякога е полезно при наследяване:
class Something:
def greet(cls, someone):
print(someone, "was greeted from", cls)
greet = classmethod(greet)
>>> Something.greet("Mityo")
Mityo was greeted from <class '__main__.Something'>
()
върху класа__init__
и взема новосъздадения обект като първи аргумент__new__
, но за него по-нататък
class Person:
def __init__(self, name, age = 20, location = "Sofia"):
self.name = name
self.age = age
self.location = location
>>> person = Person("Mityo the Python", 30, "Great Tarnovo")
class Vector:
def __init__(self, x, y, z): self._coords = list(map(float, [x, y, z]))
def length(self): return sum([_ ** 2 for _ in self._coords]) ** 0.5
def dot(self, other):
return Vector(self.y() * other.z() - self.z() * other.y(),
self.z() * other.x() - self.x() * other.z(),
self.x() * other.y() - self.y() * other.x())
def normalize(self):
self._coords = [_ / self.length() for _ in self._coords]
def x(self): return self._coords[0]
def y(self): return self._coords[1]
def z(self): return self._coords[2]
x, y = Vector(0, 2.0, 0), Vector(3.0, 0, 0)
z = x.dot(y)
z.normalize()
print(z._coords)
==
is
>>> a = ['spam', 'eggs', 42]
>>> b = ['spam', 'eggs', 42]
>>> a is b
False
>>> a == b
True
>>> c = a
>>> a == c
True
>>> a is c
True
Можете да предефинирате равенството за обекти от даден клас с метода__eq__
class Vector:
def __init__(self, x, y, z): self._coords = map(float, [x, y, z])
def __eq__(self, other):
return all([a == b for a, b in zip(self._coords, other._coords)])
По подразбиране, __eq__
е имплементирана с is
class Food: pass
spam = Food()
eggs = Food()
more_spam = spam
print(spam == more_spam, spam is more_spam) # True True
print(spam == eggs, spam is eggs) # False False
class Vector:
def __init__(self, x, y, z): self._coords = list(map(float, [x, y, z]))
def __eq__(self, other):
return all([a == b for a, b in zip(self._coords, other._coords)])
>>> a, b = Vector(1.0, 1.0, 1.0), Vector(1.0, 1.0, 1.0)
>>> print(a == b)
True
>>> print(a != b)
False
__eq__
предефинира !=
__ne__
Други методи за сравняване на обекти:
__lt__(self, other)
# self < other__le__(self, other)
# self <= other__gt__(self, other)
# self > other__ge__(self, other)
# self >= otherstr
) и "репрезентация" (repr
)str(обект)
eval(repr(обект)) == обект
repr(обект)
>>> print("Spam\nand\neggs")
Spam
and
eggs
>>> print(repr("Spam\nand\neggs"))
'Spam\nand\neggs'
Можете да дефинирате текстово представяне и репрезентация със "служебните" методи __str__
и __repr__
.
class Person:
...
def __repr__(self):
return "Person({0!r}, {1!r})".format(self.name, self.age)
def __str__(self):
return self.name
>>> mityo = Person("Mityo the Python", 33)
>>> print(str(mityo))
Mityo the Python
>>> print(repr(mityo))
Person('Mityo the Python', 33)
>>> mityo
Person('Mityo the Python', 33)
>>> eval(repr(mityo))
Person('Mityo the Python', 33)
Можете да задавате как да излиза обекта при формат.
class Spam:
def __format__(self, string):
return 'spam' + (' ' + string if string else '')
>>> print('{0}'.format(Spam()))
spam
>>> print('{0:a lot}'.format(Spam()))
spam a lot
Можете да предефинирате аритметичните оператори за вашите типове.
__add__(self, other)
за self + other
__sub__(self, other)
за self - other
__mul__(self, other)
за self * other
__truediv__(self, other)
за self / other
__floordiv__(self, other)
за self // other
__mod__(self, other)
за self % other
__lshift__(self, other)
за self << other
__rshift__(self, other)
за self >> other
__and__(self, other)
за self & other
__xor__(self, other)
за self ^ other
__or__(self, other)
за self | other
+=
, /=
и т.н.i
след двете подчертавки - __add__
става __iadd__
self
и да връщат self
a OP= b
и недефиниран __iOP__
се извиква a = a OP b
a, b, c = MagicNumber(3), MagicNumber(5), MagicNumber(7)
a = a + b # MagicNumber.__add__(a, b)
a += c # MagicNumber.__iadd__(a, c)
Има методи, които може да предефинирате, за преобразования от вашия клас към стандартен тип:
__int__(self)
за int(обект)
__float__(self)
за float(обект)
__complex__(self)
за complex(обект)
__bool__(self)
за bool(обект)
Python ви предлага и оператори, с които можете да третирате вашия клас като колекция:
__len__(self)
за len(обект)
__getitem__(self, key)
за обект[key]
__setitem__(self, key, value)
за обект[key] = value
__delitem__(self, key)
за del обект[key]
__contains__(self, item)
за item in обект
Можете да предефинирате оператора две скоби ()
.
class Stamp:
def __init__(self, name): self.name = name
def __call__(self, something):
print("{0} was stamped by {1}".format(something, self.name))
>>> stamp = Stamp("The government")
>>> stamp("That thing there")
That thing there was stamped by The government