Python进阶----Forth

1.自定义向量类

class Ve:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __iter__(self):
        return (i for i in (self.x, self.y))

    def __str__(self):
        return str(tuple(self))

    def __eq__(self, other):
        return tuple(self) == tuple(other)

    def __abs__(self):
        return self.x*self.x + self.y*self.y

    def __bool__(self):
        return bool(abs(self))


obj1 = Ve(1, 2)
obj2 = Ve(0, 0)

print(str(obj1))
print(obj1 == obj2)
print(bool(obj1), bool(obj2))
print(abs(obj1))
print(obj1)

for i in obj2:
    print(i)

输出

(1, 2)                   注释:  1.定义__str__方法实现了str()方法,其他同理
False                            2.参数为 self 即对象本身
True False                       3.__eq__方法用于判断向量是否相等
5                                4.__abs__方法用于计算向量模的平方和
0                                5.__bool__方法用于计算向量模是否为0并返回布尔值
0                                6.__iter__方法负责实现迭代,允许对象 for 循环
(1, 2)                           7.输出对象显示, 由__str__ 和 __iter__共同决定, __str__决定显示

2.格式化显示

分为 format() 和 str.format()

format()

a = 10
value = 1/3.11
h = format(value, '0.3f')       小数点后保留三位
y = format(10, 'b')             转化为2进制
j = format(1/3, '.3%')          百分号后保留三位
print([i for i in [h, y, j]])

['0.322', '1010', '33.333%']

str.format()

value = 10/3.11
result = '{result: 0.5f}'.format(result=value)     小数点后保留5print(result)

3.21543

注意:如果类没有定义 format 方法, 从 object 继承的方法会返回 str(obj)
因为我们前面Ve类定义了 str 方法,因此

format(obj1)  返回 (1, 2)   执行的是__str__方法

3.实现向量类的 format 方法

    def __format__(self, format_spec):
        result = (format(c, format_spec) for c in self)
        return '({}, {})'.format(*result)

    引用 format方法, * 可以拆元组

obj1 = Ve(1, 2)
format(obj1, '.2f')

(1.00  2.00)

4.拓展

新极坐标显示向量

规定 format(obj, 'xxxp') 以 p 结尾则极坐标显示

极坐标显示第一个参数为模长的平方,第二个为弧度

	def angle(self):
    	return math.atan2(self.y, self.x)

	定义计算弧度函数

format 函数做修改

    def __format__(self, format_spec=''):
        if format_spec.endswith('p'):
            format_spec = format_spec[:-1]
            obj = (abs(self), self.angle())                 对象即元组
        else:
            obj = self                                      对象即元组
        result = (format(c, format_spec) for c in obj)      一个生成器
        return '({}, {})'.format(*result)

    def angle(self):
        return math.atan2(self.y, self.x)


obj1 = Ve(1, 1)
print(format(obj1, '0.5fp'))

(2.00000, 0.78540)  

原功能不影响

5.可散列的向量类

实现对象的只读性----x, y分量只读

class Ve:
    def __init__(self, x, y):
        self.__x = x                   设置私有属性
        self.__y = y

    @property                          装饰器实现类方法变类属性
    def x(self):                       实现只读属性, 不能在实例化后修改, 否则报错
        return self.__x                如果属性名不为x, 修改不会报错, 但是对象的x值不会改变

    @property
    def y(self):                       实质是属性方法的覆盖
        return self.__y

    def __iter__(self):
        return (i for i in (self.__x, self.__y))

    def __str__(self):
        return str(tuple(self))


obj = Ve(3, 4)
print(obj)
print(obj.x)

(3, 4)          依然如此返回
3               

当向量不可变后,才能实现其 hash 方法

要想创建可散列的类型, 只需正确实现 __hash__ 和 __eq__ 方法, 但是实例的散列值绝不应该变化

简易实现 complex()函数

def new_complex(x, y):
    if x == 0:
        return '{}j'.format(y)
    else:
        return '({}+{}j)'.format(x, y)


result = new_complex(0, 1)                   实际上, 真正的complex()函数还会接收复数类如
result1 = new_complex(1, 0)                  3+4j, '3+4j' 作为参数并返回
print(result, result1)                       若判断参数包含复数类型则直接返回

1j (1+0j)

设置 hashrepr 方法

    def __hash__(self):                                           哈希函数
        return hash(self.x) ^ hash(self.y)

    def __repr__(self):
        class_name = type(self).__name__
        return '{}({!r}, {!r})'.format(class_name, *self)         实例化对象显示


obj = Ve(4, 4)
print(hash(obj))
print(repr(obj))

16    Ve(4, 4)

6.使用 slots 类属性节省空间

默认情况下, Python在各个实例中名为 __dict__的字典里存储实例属性, 使用散列表提升速度但字典会消耗大量内存
通过__slots__类属性,能节省大量内存,方法是让解释器在元组中存储实例属性

设置类属性

class Ve:
    __slots__ = ('__x', '__y', '__weakref__')          以元组存储, 添加弱引用属性

设置 __slots__ 属性后,实例不能再有 __slots__ 中所列名称外的其他属性

要注意的问题

1.当处理上百万数据时作用明显尤其对于列表
2.每个子类都要定义__slots__属性,因为解释器会忽略继承的__slots__属性
3.实例只能拥有__slots__中列出的属性

7.覆盖类属性

设置类属性
实例覆盖

class Ve:
    test = 'd'
    其他构造方法省略

obj = Ve(4, 4)
print(Ve.test, obj.test)
obj.test = 'f'
print(obj.test)

d d
f                        针对每个不同的实例做特定的修改

覆盖类属性有两种办法, 实例覆盖类属性和继承类覆盖类属性
继承类覆盖

class Vf(Ve):
    test = 'h'


obj = Vf(1, 2)
print(Vf.test, obj.test)

h  h                         多用于Django框架中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值