Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4880524

Browse files
committed
接口,协议
1 parent 9d7ee22 commit 4880524

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

‎09-pythonic-obj/vector2d.py‎

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from array import array
4+
import math
5+
6+
7+
class Vector2d:
8+
__slots__ = ('_x', '_y')
9+
10+
typecode = 'd'
11+
12+
def __init__(self, x, y):
13+
# python 会把双下划线 __x 变成 __Vector2d_x,把 __y 变成 __Vector2d_y。
14+
# 而单下划线开头的属性不做任何处理。
15+
self.__x = float(x)
16+
self.__y = float(y)
17+
18+
@property
19+
def x(self):
20+
return self.__x
21+
22+
@property
23+
def y(self):
24+
return self.__y
25+
26+
def __iter__(self):
27+
return (i for i in (self.x, self.y))
28+
29+
def __repr__(self):
30+
class_name = type(self).__name__
31+
return '{}(!r), (!r)'.format(class_name, *self)
32+
33+
def __str__(self):
34+
return str(tuple(self))
35+
36+
def __bytes__(self):
37+
return (bytes([ord(self.typecode)]) +
38+
bytes(array(self.typecode, self)))
39+
40+
def __eq__(self, other):
41+
return tuple(self) == tuple(other)
42+
43+
def __hash__(self):
44+
return hash(self.x) ^ hash(self.y)
45+
46+
def __abs__(self):
47+
return math.hypot(self.x, self.y)
48+
49+
def __bool__(self):
50+
return bool(abs(self))
51+
52+
def __format__(self, fmt_spec=''):
53+
if fmt_spec.endswith('p'):
54+
fmt_spec = fmt_spec[:-1]
55+
coords = (abs(self), self.angle())
56+
outer_fmt = '<{}, {}>'
57+
else:
58+
coords = self
59+
outer_fmt = '({}, {})'
60+
61+
components = (format(c, fmt_spec) for c in coords)
62+
return outer_fmt.format(*components)
63+
64+
def angle(self):
65+
return math.atan2(self.y, self.x)
66+
67+
# 备选构造方法,从字节序列转换成Vector2d实例
68+
@classmethod
69+
def frombytes(cls, octets):
70+
typecode = chr(octets[0])
71+
memv = memoryview(octets[1:]).cast(typecode)
72+
return cls(*memv)

‎10-seq-hacking/vector.py‎

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from array import array
4+
import reprlib
5+
import math
6+
import numbers
7+
import functools
8+
import operator
9+
import itertools
10+
11+
12+
class Vector:
13+
typecode = 'd'
14+
15+
def __init__(self, components):
16+
self._components = array(self.typecode, components)
17+
18+
def __iter__(self):
19+
return iter(self._components)
20+
21+
def __repr__(self):
22+
components = reprlib.repr(self._components)
23+
components = components[components.find('['):-1]
24+
return f'Vector({components})'
25+
26+
def __str__(self):
27+
return str(tuple(self))
28+
29+
def __bytes__(self):
30+
return (bytes([ord(self.typecode)]) + bytes(self._components))
31+
32+
def __eq__(self, other):
33+
return (len(self) == len(other)) and all(a == b for a, b in zip(self, other))
34+
35+
def __hash__(self):
36+
hashes = map(hash, self._components)
37+
return functools.reduce(operator.xor, hashes, 0)
38+
39+
def __abs__(self):
40+
return math.sqrt(sum(x * x for x in self))
41+
42+
def __bool__(self):
43+
return bool(abs(self))
44+
45+
def __len__(self):
46+
return len(self._components)
47+
48+
def __getitem__(self, index):
49+
cls = type(self)
50+
if isinstance(index, slice):
51+
return cls(self._components[index])
52+
elif isinstance(index, numbers.Integral):
53+
return self._components[index]
54+
else:
55+
msg = f'{cls.__name__} indices must be integers'
56+
raise TypeError(msg)
57+
58+
shortcut_names = 'xyzt'
59+
60+
def __getattr__(self, name):
61+
cls = type(self)
62+
if len(name) == 1:
63+
pos = cls.shortcut_names.find(name)
64+
if 0 <= pos < len(self._components):
65+
return self._components[pos]
66+
msg = f'{cls.__name__} object has no attribute {name}'
67+
raise AttributeError(msg)
68+
69+
def __setattr__(self, name, value):
70+
cls = type(self)
71+
if len(name) == 1:
72+
if name in cls.shortcut_names:
73+
error = f'readonly attribute {name}'
74+
elif name.islower():
75+
error = f"can't set attributes 'a' to 'z' in {cls.__name__}"
76+
else:
77+
error = ''
78+
if error:
79+
raise AttributeError(error)
80+
super().__setattr__(name, value)
81+
82+
def angle(self, n):
83+
r = math.sqrt(sum(x * x for x in self[n:]))
84+
a = math.atan2(r, self[n - 1])
85+
if (n == len(self) - 1) and (self[-1] < 0):
86+
return math.pi * 2 - a
87+
else:
88+
return a
89+
90+
def angles(self):
91+
return (self.angle(n) for n in range(1, len(self)))
92+
93+
def __format__(self, fmt_spec=''):
94+
if fmt_spec.endswith('h'):
95+
fmt_spec = fmt_spec[:-1]
96+
coords = itertools.chain([abs(self)], self.angles())
97+
out_fmt = '<{}>'
98+
else:
99+
coords = self
100+
out_fmt = '({})'
101+
components = (format(c, fmt_spec) for c in coords)
102+
return out_fmt.format(', '.join(components))
103+
104+
@classmethod
105+
def frombytes(cls, octets):
106+
typecode = chr(octets[0])
107+
memv = memoryview(octets[1:]).cast(typecode)
108+
return cls(memv)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /