python 自定义类(特殊方法)

文章目录

    • 1. 对象表示形式
    • 2. 可散列的类
    • 3. 私有属性的利弊
    • 4. `__slots__` 类属性节省空间
    • 5. 覆盖类属性

learn from 《流畅的python》

from array import array
import mathclass Vector2D:typecode = 'd'  # 类属性def __init__(self, x, y):self.x = float(x)self.y = float(y)@classmethod  # 装饰器, 函数不需要传入 self 参数,需要cls 传入类本身# classmethod 最常见的用途是 定义备选构造方法# @staticmethod 就是定义在类中的普通函数def frombytes(cls, octets):typecode = chr(octets[0])memv = memoryview(octets[1:]).cast(typecode)return cls(*memv)  # 构造类对象@staticmethoddef hello():print("hello world!")def __iter__(self):  # 可迭代对象,才能拆包 x,y = my_vectorreturn (i for i in (self.x, self.y))  # 生成器表达式def __repr__(self):class_name = type(self).__name__return '{}({!r},{!r})'.format(class_name, *self)# {!r} 获取 *self 的分量,可迭代对象def __str__(self):return str(tuple(self))  # 从可迭代对象生成元组def __bytes__(self):return (bytes([ord(self.typecode)]) + bytes(array(self.typecode, self)))def __eq__(self, other):return tuple(self) == tuple(other)def __abs__(self):return math.hypot(self.x, self.y)def __bool__(self):return bool(abs(self))

1. 对象表示形式

  • repr() 返回便于 开发者 理解的对象字符串形式,须实现__repr()__
  • str() 返回便于 用户 理解的对象字符串形式,须实现__str()__
  • __format()__ 会被内置的 format(), str.format() 调用
>>> brl = 1/2.43
>>> brl
0.4115226337448559
>>> format(brl, "0.4f")
'0.4115'
>>> format(brl, ".4f")
'0.4115'
>>> "1 BRL = {rate:0.2f} USD".format(rate=brl)
'1 BRL = 0.41 USD'

https://docs.python.org/3/library/string.html#formatspec

v1 = Vector2D(315687,4)
print("test str {0.x:5.3e}".format(v1))
# test str 3.157e+05

{ 变量 :格式说明符 } 包含两部分

>>> format(8, 'b') # 二进制
'1000'
>>> format(1/3, '.2%') # %百分比
'33.33%' 
  • 如果类没有定义 __format__ 方法,从 object 继承的方法会返回 str(my_object),调用 __str__()
print(format(v1)) # (315687.0, 4.0)
print(format(v1, '.3f')) # TypeError: unsupported format string passed to Vector2D.__format__

为了解决该问题,在类中添加方法:

    def __format__(self, fmt_spec=""):components = (format(c, fmt_spec) for c in self)# 使用内置的 format 把格式应用到各个分量上,构成一个可迭代的字符串return "({}, {})".format(*components) # 格式化字符串
print(format(v1, '.3f')) # (315687.000, 4.000)
  • 自定义极坐标表示
    def angle(self):return math.atan2(self.y, self.x)def __format__(self, fmt_spec=""):if fmt_spec.endswith('p'): # 以 p 结尾的用极坐标fmt_spec = fmt_spec[:-1]coords = (abs(self), self.angle())outer_fmt = "<{}, {}>"else:coords = selfouter_fmt = "({}, {})"components = (format(c, fmt_spec) for c in coords)return outer_fmt.format(*components)
print(format(Vector2D(1, 1), 'p'))
print(format(Vector2D(1, 1), '.3ep'))
print(format(Vector2D(1, 1), '0.5fp'))
print(format(Vector2D(1, 1), '0.2f'))<1.4142135623730951, 0.7853981633974483>
<1.414e+00, 7.854e-01>
<1.41421, 0.78540>
(1.00, 1.00)

2. 可散列的类

hash(v1) # TypeError: unhashable type: 'Vector2D'

为了可以散列,需要实现__hash__(), __eq__()

    def __init__(self, x, y):self.__x = float(x)self.__y = float(y)@propertydef x(self):return self.__x@property  #  @property 装饰器把读值方法标记为特性def y(self):return self.__y
v1.__x = 100  # 值不可以变更
print(v1) # (315687.0, 4.0)
# v1.x = 100 # AttributeError: can't set attribute
  • 添加 __hash__()
    def __hash__(self):return hash(self.x) ^ hash(self.y)
v2 = Vector2D(10, 20)
v3 = Vector2D(10, 20)
print(hash(v1))  # 315683
print(hash(v2))  # 30
print(v2 is v3)  # False
print(hash(v3))  # 30
print(set([v1, v2, v3])) # {Vector2D(315687.0,4.0), Vector2D(10.0,20.0)}

3. 私有属性的利弊

  • 如果子类跟父类有相同的属性,子类会覆盖父类
  • __ or _开头的属性将会被存在 实例的 __dict__ 属性内,且加上前缀 _类名
print(v1.__dict__)
# {'_Vector2D__x': 315687.0, '_Vector2D__y': 4.0, '__x': 100}
print(v1._Vector2D__x)  # 315687.0

名称改写是一种安全措施,不能保证万无一失:它的目的是避免意外访问,不能防止故意做错事

Python 解释器不会对使用 单个下划线 的属性名做特殊处理,不过这是很多 Python 程序员严格遵守的约定,他们不会在类外部访问这种属性。

print(v1._Vector2D__x)  # 315687.0
v1._Vector2D__x = 100
print(v1._Vector2D__x)  # 100
print(v1)  # (100., 4.0)

不能真正的实现 私有和不可变

4. __slots__ 类属性节省空间

class Vector2d: __slots__ = ('__x', '__y')

等号右侧可以是可迭代的对象,里面存储所有实例属性的名称的字符串,从而避免使用消耗内存的 __dict__ 属性

  • 在类中定义 __slots__ 属性之后,实例不能再有 __slots__ 中所列名称之外的其他属性
  • 为了 让对象支持弱引用,必须有 __weakref__属性。用户定义的类中 默认就有 __weakref__ 属性。
    可是,如果类中定义了 __slots__ 属性,而且想把实例作为 弱引用 的目标,那么要把 __weakref__ 添加到 __slots__
  • 一般不要把 __dict__ 加入到 __slots__
  • 每个子类都要定义 __slots__ 属性,因为解释器会忽略继承的 __slots__ 属性

5. 覆盖类属性

print(v1.typecode)  # d
print(v2.typecode)  # d
print(bytes(v1))  # b'd\x00\x00\x00\x00\x00\x00Y@\x00\x00\x00\x00\x00\x00\x10@'
print(Vector2D.typecode)  # dv1.typecode = 'f'
print(v1.typecode)  # f
print(bytes(v1))  # b'f\x00\x00\xc8B\x00\x00\x80@'
print(Vector2D.typecode)  # d
v1.typecode = 'd'
print(v1.typecode)  # dVector2D.typecode = 'f'
print(Vector2D.typecode)  # f
print(v1.typecode)  # d
print(v2.typecode)  # f
  • typecode 是类属性,一旦实例对象赋值 typecode后,实际是创建了新的实例属性
  • 如果为不存在的 实例属性 赋值,会 新建 实例属性,类属性不受影响,但是实例属性会遮盖同名类属性

还可以订制类的数据属性:

class anOtherVec(Vector2D):typecode = 'f' # 只是修改子类的数据类型v4 = anOtherVec(3,4)
print(bytes(v4))

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471985.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络知识

http://www.cnblogs.com/dawen/archive/2011/05/18/2050358.html http://www.cnblogs.com/daoluanxiaozi/p/3274925.html转载于:https://www.cnblogs.com/webundle/p/4505782.html

datagridview 动态插入图片_挑战一张照片制作动态PPT背景

在PPT中&#xff0c;要做出好看的页面动画效果&#xff0c;常常需要用很多图片和装饰元素。而如果你手头的素材只有一张照片&#xff0c;如何才能快速做出好看的PPT背景效果呢&#xff1f;本期内容&#xff0c;我们就来一起挑战&#xff0c;使用一张照片&#xff0c;制作PPT动态…

sed搜索某行在行末追加_示范sed指定某行插入 追加和全局替换

有时候会有这样的需求&#xff0c;在指定的行后面或者是前面追加一行&#xff0c;这个时候可以使用sed来完成&#xff0c;具体用法如下a\ 在指定的行后面追加一行b\ 在指定的行前面追加一行使用指定的行号追加内容&#xff0c;在使用行号的过程中&#xff0c;需要注意的问题有以…

LeetCode 1941. 检查是否所有字符出现次数相同

文章目录1. 题目2. 解题1. 题目 给你一个字符串 s &#xff0c;如果 s 是一个 好 字符串&#xff0c;请你返回 true &#xff0c;否则请返回 false 。 如果 s 中出现过的 所有 字符的出现次数 相同 &#xff0c;那么我们称字符串 s 是 好 字符串。 示例 1&#xff1a; 输入&…

java初学者定远期目标_JAVA题,新手求解

展开全部类图设计&#xff1a;类设计&#xff1a;package car;public class Car {private String id;private String name;public void setId(String id) {this.id id;}public void setName(String name) {this.name name;}/*** 获取汽车编e69da5e6ba9062616964757a686964616…

LeetCode 1942. 最小未被占据椅子的编号(set)

文章目录1. 题目2. 解题1. 题目 有 n 个朋友在举办一个派对&#xff0c;这些朋友从 0 到 n - 1 编号。 派对里有 无数 张椅子&#xff0c;编号为 0 到 infinity 。 当一个朋友到达派对时&#xff0c;他会占据 编号最小 且未被占据的椅子。 比方说&#xff0c;当一个朋友到达时…

python哪本书好看_python入门看哪本书好

推荐几本适合python初学者的书。《Python编程 从入门到实战》本书中涵盖的内容是比较精简的&#xff0c;没有艰深晦涩的概念&#xff0c;最重要的是每个小结都附带有”动手试一试”环节&#xff0c;学编程最佳的方式就是多动手、多动脑。很多初学者看完书之后不知道下一步怎么办…

java mysql geo_GEO数据库简介

为了支持公共使用和散布基因表达数据&#xff0c;NCBI开始了基因表达汇编(GEO)计划。GEO是努力建立一个基因表达数据仓库和在线资源&#xff0c;用于从任何物种或人造的来源检索基因表达数据。来自microarray&#xff0c;高密度寡核苷酸array(HAD)&#xff0c;杂交膜(filter)和…

对每个小组的评论和建议

1、极速蜗牛&#xff1a;总体上已经有了一个小游戏的基本轮廓&#xff0c;虽然还没有达到预期的效果&#xff0c;但是能看到他们的进度。不过这次我们只看到了一直在反弹&#xff0c;对于一个游戏来说&#xff0c;娱乐性是很重要的&#xff0c;但是在这个游戏中我们没有看到很大…

vue路由懒加载_优化vue项目的首屏加载速度

最近使用vue-cli3构建了一个小型的博客系统&#xff0c;完工之后&#xff0c;build打包出来发现一个chunk-vendors包就有1.1m&#xff0c;部署上去之后&#xff0c;访问的时候&#xff0c;首屏加载非常慢。居然需要21s&#xff0c;体验极差。这是打包的结果截图根据这种情况&am…

LeetCode 1943. 描述绘画结果(差分思想)

文章目录1. 题目2. 解题1. 题目 给你一个细长的画&#xff0c;用数轴表示。 这幅画由若干有重叠的线段表示&#xff0c;每个线段有 独一无二 的颜色。 给你二维整数数组 segments &#xff0c;其中 segments[i] [starti, endi, colori] 表示线段为 半开区间 [starti, endi) 且…

java浏览器拖拽_使用Java强制移动浏览器缩小

在我的网络应用中&#xff0c;我有一些缩略图&#xff0c;可在单击时打开一个灯箱。 在移动设备上&#xff0c;缩略图很小&#xff0c;用户通常会放大。问题是&#xff0c;单击播放时&#xff0c;灯箱在可见区域之外(他们必须滚动到灯箱才能观看视频)。 是否可以强制移动浏览器…

Git学习笔记01--初始化设置

1、查看git版本 $ git --version 2、设置用户姓名和邮箱 $ git config --global user.name “Craftor” $ git config --global usrer.email “craftor0924gmail.com” 3、设置命令别名 $ git config --system alias.st status $ git config --system alias.ci commit $ git co…

LeetCode 1944. 队列中可以看到的人数(单调栈)

文章目录1. 题目2. 解题1. 题目 有 n 个人排成一个队列&#xff0c;从左到右 编号为 0 到 n - 1 。 给你以一个整数数组 heights &#xff0c;每个整数 互不相同&#xff0c;heights[i] 表示第 i 个人的高度。 一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他…

yolov2训练_一文看懂YOLO v2

我的CSDN博客&#xff1a;https://blog.csdn.net/litt1e我的公众号&#xff1a;工科宅生活概述新的YOLO版本论文全名叫“YOLO9000: Better, Faster, Stronger”&#xff0c;相较于YOLO主要有两个大方面的改进&#xff1a;第一&#xff0c;作者使用了一系列的方法对原来的YOLO多…

mysql 字符串搜_mysql – 在表中搜索字符串的SQL查询?

嗨,我想在存储在mysql数据库中的表中搜索特定的字符串.表格结构如下&#xff1a; –--------------------------------------------------------------------------| day | 9-10 | 10-11 | 11-12 | 12-1 | 1-2 | 2-3 | 3-4 ||------------------------------------------------…

python语言画心_python语言还是java如何用python画爱心

用python绘制爱心的基本步骤如下&#xff1a;002pc.com对《python语言还是java如何用python画爱心》总结来说&#xff0c;为我们学习Python很实用。首先先下载安装好python程序。在我们自己的电脑上找到python 的IDLE工具。2.然后打开IDLE,新建一个文件&#xff0c;命名为test1…

java的foeachr循环_for循环和Dowhile循环的应用

DoWhile循环{public static void main(String[] args) {int i 0;int sum 0;do {sum sum i;i;} while (i < 100);System.out.println(sum);}}{int a 0;while (a<0){System.out.println(a);a;}System.out.println("");do {System.out.println(a);a;}while (…

LeetCode 1945. 字符串转化后的各位数字之和

文章目录1. 题目2. 解题1. 题目 给你一个由小写字母组成的字符串 s &#xff0c;以及一个整数 k 。 首先&#xff0c;用字母在字母表中的位置替换该字母&#xff0c;将 s 转化 为一个整数&#xff08;也就是&#xff0c;‘a’ 用 1 替换&#xff0c;‘b’ 用 2 替换&#xff…

codeforces 303 div2 E

赤裸裸的最短路&#xff0c;需要注意下枚举过程就好了。直接贴上别人的代码&#xff0c;发现他的代码挺符合我的风格&#xff0c;以后就这样写了。#include <bits/stdc.h>using namespace std;struct node{int y,z,id;node(){}node(int y,int z,int id):y(y),z(z),id(id)…