这可能是Python面向对象编程的最佳实践
作者 | 崔庆才
来源 | 进击的Coder(ID:FightingCoder)
Python 是支持面向对象的,很多情况下使用面向对象编程会使得代码更加容易扩展,并且可维护性更高,但是如果你写的多了或者某一对象非常复杂了,其中的一些写法会相当相当繁琐,而且我们会经常碰到对象和 JSON 序列化及反序列化的问题,原生的 Python 转起来还是很费劲的。
可能这么说大家会觉得有点抽象,那么这里举几个例子来感受一下。
首先让我们定义一个对象吧,比如颜色。我们常用 RGB 三个原色来表示颜色,R、G、B 分别代表红、绿、蓝三个颜色的数值,范围是 0-255,也就是每个原色有 256 个取值。如 RGB(0, 0, 0) 就代表黑色,RGB(255, 255, 255) 就代表白色,RGB(255, 0, 0) 就代表红色,如果不太明白可以具体看看 RGB 颜色的定义哈。
好,那么我们现在如果想定义一个颜色对象,那么正常的写法就是这样了,创建这个对象的时候需要三个参数,就是 R、G、B 三个数值,定义如下:
其实对象一般就是这么定义的,初始化方法里面传入各个参数,然后定义全局变量并赋值这些值。其实挺多常用语言比如 Java、PHP 里面都是这么定义的。但其实这种写法是比较冗余的,比如 r、g、b 这三个变量一写就写了三遍。
好,那么我们初始化一下这个对象,然后打印输出下,看看什么结果:
结果是什么样的呢?或许我们也就能看懂一个 Color 吧,别的都没有什么有效信息,像这样子:
我们知道,在 Python 里面想要定义某个对象本身的打印输出结果的时候,需要实现它的__repr__
方法,所以我们比如我们添加这么一个方法:
这里使用了 Python 中的 fstring 来实现了 __repr__
方法,在这里我们构造了一个字符串并返回,字符串中包含了这个 Color 类中的 r、g、b 属性,这个返回的结果就是 print 的打印结果,我们再重新执行一下,结果就变成这样子了:
改完之后,这样打印的对象就会变成这样的字符串形式了,感觉看起来清楚多了吧?
再继续,如果我们要想实现这个对象里面的 __eq__
、__lt__
等各种方法来实现对象之间的比较呢?照样需要继续定义成类似这样子的形式:
这里是 __lt__
方法,有了这个方法就可以使用比较符来对两个 Color 对象进行比较了,但这里又把这几个属性写了两遍。
最后再考虑考虑,如果我要把 JSON 转成 Color 对象,难道我要读完 JSON 然后一个个属性赋值吗?如果我想把 Color 对象转化为 JSON,又得把这几个属性写几遍呢?如果我突然又加了一个属性比如透明度 a 参数,那么整个类的方法和参数都要修改,这是极其难以扩展的。不知道你能不能忍,反正我不能忍!
如果你用过 Scrapy、Django 等框架,你会发现 Scrapy 里面有一个 Item 的定义,只需要定义一些 Field 就可以了,Django 里面的 Model 也类似这样,只需要定义其中的几个字段属性就可以完成整个类的定义了,非常方便。
说到这里,我们能不能把 Scrapy 或 Django 里面的定义模式直接拿过来呢?能是能,但是没必要,因为我们还有专门为 Python 面向对象而专门诞生的库,没错,就是 attrs 和 cattrs 这两个库。
有了 attrs 库,我们就可以非常方便地定义各个对象了,另外对于 JSON 的转化,可以进一步借助 cattrs 这个库,非常有帮助。
说了这么多,还是没有介绍这两个库的具体用法,下面我们来详细介绍下。
安装
安装这两个库非常简单,使用 pip 就好了,命令如下:
安装好了之后我们就可以导入并使用这两个库了。
简介与特性
首先我们来介绍下 attrs 这个库,其官方的介绍如下:
attrs 是这样的一个 Python 工具包,它能将你从繁综复杂的实现上解脱出来,享受编写 Python 类的快乐。它的目标就是在不减慢你编程速度的前提下,帮助你来编写简洁而又正确的代码。
其实意思就是用了它,定义和实现 Python 类变得更加简洁和高效。
基本用法
首先明确一点,我们现在是装了 attrs 和 cattrs 这两个库,但是实际导入的时候是使用 attr 和 cattr 这两个包,是不带 s 的。
在 attr 这个库里面有两个比较常用的组件叫做 attrs 和 attr,前者是主要用来修饰一个自定义类的,后者是定义类里面的一个字段的。有了它们,我们就可以将上文中的定义改写成下面的样子:
看我们操作的,首先我们导入了刚才所说的两个组件,然后用 attrs 里面修饰了 Color 这个自定义类,然后用 attrib 来定义一个个属性,同时可以指定属性的类型和默认值。最后打印输出,结果如下:
怎么样,达成了一样的输出效果!
观察一下有什么变化,是不是变得更简洁了?r、g、b 三个属性都只写了一次,同时还指定了各个字段的类型和默认值,另外也不需要再定义 __init__
方法和 __repr__
方法了,一切都显得那么简洁。一个字,爽!
实际上,主要是 attrs 这个修饰符起了作用,然后根据定义的 attrib 属性自动帮我们实现了__init__
、__repr__
、__eq__
、__ne__
、__lt__
、__le__
、__gt__
、__ge__
、__hash__
这几个方法。
如使用 attrs 修饰的类定义是这样子:
其实就相当于已经实现了这些方法:
所以说,如果我们用了 attrs 的话,就可以不用再写这些冗余又复杂的代码了。
翻看源码可以发现,其内部新建了一个 ClassBuilder,通过一些属性操作来动态添加了上面的这些方法,如果想深入研究,建议可以看下 attrs 库的源码。
别名使用
这时候大家可能有个小小的疑问,感觉里面的定义好乱啊,库名叫做 attrs,包名叫做 attr,然后又导入了 attrs 和 attrib,这太奇怪了。为了帮大家解除疑虑,我们来梳理一下它们的名字。
首先库的名字就叫做 attrs,这个就是装 Python 包的时候这么装就行了。但是库的名字和导入的包的名字确实是不一样的,我们用的时候就导入 attr 这个包就行了,里面包含了各种各样的模块和组件,这是完全固定的。
好,然后接下来看看 attr 包里面包含了什么,刚才我们引入了 attrs 和 attrib。
首先是 attrs,它主要是用来修饰 class 类的,而 attrib 主要是用来做属性定义的,这个就记住它们两个的用法就好了。
翻了一下源代码,发现其实它还有一些别名:
也就是说,attrs 可以用 s 或 attributes 来代替,attrib 可以用 attr 或 ib 来代替。
既然是别名,那么上面的类就可以改写成下面的样子:
是不是更加简洁了,当然你也可以把 s 改写为 attributes,ib 改写为 attr,随你怎么用啦。
不过我觉得比较舒服的是 attrs 和 attrib 的搭配,感觉可读性更好一些,当然这个看个人喜好。
所以总结一下:
库名:attrs
导入包名:attr
修饰类:s 或 attributes 或 attrs
定义属性:ib 或 attr 或 attrib
OK,理清了这几部分内容,我们继续往下深入了解它的用法吧。
声明和比较
在这里我们再声明一个简单一点的数据结构,比如叫做 Point,包含 x、y 的坐标,定义如下:
其中 attrib 里面什么参数都没有,如果我们要使用的话,参数可以顺次指定,也可以根据名字指定,如:
其效果都是一样的,打印输出结果如下:
OK,接下来让我们再验证下类之间的比较方法,由于使用了 attrs,相当于我们定义的类已经有了 __eq__
、__ne__
、__lt__
、__le__
、__gt__
、__ge__
这几个方法,所以我们可以直接使用比较符来对类和类之间进行比较,下面我们用实例来感受一下:
运行结果如下:
可能有的朋友不知道 ne、lt、le 什么的是什么意思,不过看到这里你应该明白啦,ne 就是 Not Equal 的意思,就是不相等,le 就是 Less or Equal 的意思,就是小于或等于。
其内部怎么实现的呢,就是把类的各个属性转成元组来比较了,比如 Point(1, 2) < Point(3, 4)
实际上就是比较了 (1, 2)
和 (3, 4)
两个元组,那么元组之间的比较逻辑又是怎样的呢,这里就不展开了,如果不明白的话可以参考官方文档:https://docs.python.org/3/library/stdtypes.html#comparisons。
属性定义
现在看来,对于这个类的定义莫过于每个属性的定义了,也就是 attrib 的定义。对于 attrib 的定义,我们可以传入各种参数,不同的参数对于这个类的定义有非常大的影响。
下面我们就来详细了解一下每个属性的具体参数和用法吧。
首先让我们概览一下总共可能有多少可以控制一个属性的参数,我们用 attrs 里面的 fields 方法可以查看一下:
这就可以输出 Point 的所有属性和对应的参数,结果如下:
输出出来了,可以看到结果是一个元组,元组每一个元素都其实是一个 Attribute 对象,包含了各个参数,下面详细解释下几个参数的含义:
name:属性的名字,是一个字符串类型。
default:属性的默认值,如果没有传入初始化数据,那么就会使用默认值。如果没有默认值定义,那么就是 NOTHING,即没有默认值。
validator:验证器,检查传入的参数是否合法。
init:是否参与初始化,如果为 False,那么这个参数不能当做类的初始化参数,默认是 True。
metadata:元数据,只读性的附加数据。
type:类型,比如 int、str 等各种类型,默认为 None。
converter:转换器,进行一些值的处理和转换器,增加容错性。
kw_only:是否为强制关键字参数,默认为 False。
属性名
对于属性名,非常清楚了,我们定义什么属性,属性名就是什么,例如上面的例子,定义了:
那么其属性名就是 x。
默认值
对于默认值,如果在初始化的时候没有指定,那么就会默认使用默认值进行初始化,我们看下面的一个实例:
在这里我们将 y 属性的默认值设置为了 100,在初始化的时候,第一次都传入了 x、y 两个参数,第二次只传入了 x 这个参数,看下运行结果:
可以看到结果,当设置了默认参数的属性没有被传入值时,他就会使用设置的默认值进行初始化。
那假如没有设置默认值但是也没有初始化呢?比如执行下:
那么就会报错了,错误如下:
所以说,如果一个属性,我们一旦没有设置默认值同时没有传入的话,就会引起错误。所以,一般来说,为了稳妥起见,设置一个默认值比较好,即使是 None 也可以的。
初始化
如果一个类的某些属性不想参与初始化,比如想直接设置一个初始值,一直固定不变,我们可以将属性的 init 参数设置为 False,看一个实例:
比如 x 我们只想在初始化的时候设置固定值,不想初始化的时候被改变和设定,我们将其设置了 init 参数为 False,同时设置了一个默认值,如果不设置默认值,默认为 NOTHING。然后初始化的时候我们只传入了一个值,其实也就是为 y 这个属性赋值。
这样的话,看下运行结果:
没什么问题,y 被赋值为了我们设置的值 3。
那假如我们非要设置 x 呢?会发生什么,比如改写成这样子:
报错了,错误如下:
参数过多,也就是说,已经将 init 设置为 False 的属性就不再被算作可以被初始化的属性了。
强制关键字
强制关键字是 Python 里面的一个特性,在传入的时候必须使用关键字的名字来传入,如果不太理解可以再了解下 Python 的基础。
设置了强制关键字参数的属性必须要放在后面,其后面不能再有非强制关键字参数的属性,否则会报这样的错误:
好,我们来看一个例子,我们将最后一个属性设置 kw_only 参数为 True:
如果设置了 kw_only 参数为 True,那么在初始化的时候必须传入关键字的名字,这里就必须指定 y 这个名字,运行结果如下:
如果没有指定 y 这个名字,像这样调用:
那么就会报错:
所以,这个参数就是设置初始化传参必须要用名字来传,否则会出现错误。
注意,如果我们将一个属性设置了 init 为 False,那么 kw_only 这个参数会被忽略。
验证器
有时候在设置一个属性的时候必须要满足某个条件,比如性别必须要是男或者女,否则就不合法。对于这种情况,我们就需要有条件来控制某些属性不能为非法值。
下面我们看一个实例:
在这里我们定义了一个验证器 Validator 方法,叫做 is_valid_gender。然后定义了一个类 Person 还有它的两个属性 name 和 gender,其中 gender 定义的时候传入了一个参数 validator,其值就是我们定义的 Validator 方法。
这个 Validator 定义的时候有几个固定的参数:
instance:类对象
attribute:属性名
value:属性值
这是三个参数是固定的,在类初始化的时候,其内部会将这三个参数传递给这个 Validator,因此 Validator 里面就可以接受到这三个值,然后进行判断即可。在 Validator 里面,我们判断如果不是男性或女性,那么就直接抛出错误。
下面做了两个实验,一个就是正常传入 male,另一个写错了,写的是 mlae,观察下运行结果:
OK,结果显而易见了,第二个报错了,因为其值不是正常的性别,所以程序直接报错终止。
注意在 Validator 里面返回 True 或 False 是没用的,错误的值还会被照常复制。所以,一定要在 Validator 里面 raise 某个错误。
另外 attrs 库里面还给我们内置了好多 Validator,比如判断类型,这里我们再增加一个属性 age,必须为 int 类型:
这时候初始化的时候就必须传入 int 类型,如果为其他类型,则直接抛错:
另外还有其他的一些 Validator,比如与或运算、可执行判断、可迭代判断等等,可以参考官方文档:https://www.attrs.org/en/stable/api.html#validators。
另外 validator 参数还支持多个 Validator,比如我们要设置既要是数字,又要小于 100,那么可以把几个 Validator 放到一个列表里面并传入:
这样就会将所有的 Validator 都执行一遍,必须每个 Validator 都满足才可以。这里 age 传入了 500,那么不符合第二个 Validator,直接抛错:
转换器
其实很多时候我们会不小心传入一些形式不太标准的结果,比如本来是 int 类型的 100,我们传入了字符串类型的 100,那这时候直接抛错应该不好吧,所以我们可以设置一些转换器来增强容错机制,比如将字符串自动转为数字等等,看一个实例:
看这里,我们定义了一个方法,可以将值转化为数字类型,如果不能转,那么就返回 None,这样保证了任何可以被转数字的值都被转为数字,否则就留空,容错性非常高。
运行结果如下:
类型
为什么把这个放到最后来讲呢,因为 Python 中的类型是非常复杂的,有原生类型,有 typing 类型,有自定义类的类型。
首先我们来看看原生类型是怎样的,这个很容易理解了,就是普通的 int、float、str 等类型,其定义如下:
这里我们将 x 属性定义为 int 类型了,初始化的时候传入了数值型 100 和字符串型 100,结果如下:
但我们发现,虽然定义了,但是不会被自动转类型的。
另外我们还可以自定义 typing 里面的类型,比如 List,另外 attrs 里面也提供了类型的定义:
这里我们引入了 typing 这个包,定义了 y 为 int 数字组成的列表,z 使用了 attrs 里面定义的 Factory 定义了同样为列表类型。
另外我们也可以进行类型的嵌套,比如像这样子:
在这里我们定义了 Point 类代表离散点,随后定义了线,其拥有 points 属性是 Point 组成的列表。在初始化的时候我们声明了五个点,然后用这五个点组成的列表声明了一条线,逻辑没什么问题。
运行结果:
可以看到这里我们得到了一个嵌套类型的 Line 对象,其值是 Point 类型组成的列表。
以上便是一些属性的定义,把握好这些属性的定义,我们就可以非常方便地定义一个类了。
序列转换
在很多情况下,我们经常会遇到 JSON 等字符串序列和对象互相转换的需求,尤其是在写 REST API、数据库交互的时候。
attrs 库的存在让我们可以非常方便地定义 Python 类,但是它对于序列字符串的转换功能还是比较薄弱的,cattrs 这个库就是用来弥补这个缺陷的,下面我们再来看看 cattrs 这个库。
cattrs 导入的时候名字也不太一样,叫做 cattr,它里面提供了两个主要的方法,叫做 structure 和 unstructure,两个方法是相反的,对于类的序列化和反序列化支持非常好。
基本转换
首先我们来看看基本的转换方法的用法,看一个基本的转换实例:
在这里我们定义了一个 Point 对象,然后调用 unstructure 方法即可直接转换为 JSON 字符串。如果我们再想把它转回来,那就需要调用 structure 方法,这样就成功转回了一个 Point 对象。
看下运行结果:
当然这种基本的来回转用的多了就轻车熟路了。
多类型转换
另外 structure 也支持一些其他的类型转换,看下实例:
这里面用到了 Tuple、MutableSequence、Optional、Set 等类,都属于 typing 这个模块,后面我会写内容详细介绍这个库的用法。
不过总的来说,大部分情况下,JSON 和对象的互转是用的最多的。
属性处理
上面的例子都是理想情况下使用的,但在实际情况下,很容易遇到 JSON 和对象不对应的情况,比如 JSON 多个字段,或者对象多个字段。
我们先看看下面的例子:
在这里,JSON 多了一个字段 z,而 Point 类只有 x、y 两个字段,那么直接执行 structure 会出现什么情况呢?
不出所料,报错了。意思是多了一个参数,这个参数并没有被定义。
这时候一般的解决方法的直接忽略这个参数,可以重写一下 structure 方法,定义如下:
这里定义了一个 drop_nonattrs 方法,用于从 JSON 里面删除对象里面不存在的属性,然后调用新的 structure 方法即可,写法如下:
这样我们就可以避免 JSON 字段冗余导致的转换问题了。
另外还有一个常见的问题,那就是数据对象转换,比如对于时间来说,在对象里面声明我们一般会声明为 datetime 类型,但在序列化的时候却需要序列化为字符串。
所以,对于一些特殊类型的属性,我们往往需要进行特殊处理,这时候就需要我们针对某种特定的类型定义特定的 hook 处理方法,这里就需要用到 register_unstructure_hook 和 register_structure_hook 方法了。
下面这个例子是时间 datetime 转换的时候进行的处理:
在这里我们对 datetime 这个类型注册了两个 hook,当序列化的时候,就调用 strftime 方法转回字符串,当反序列化的时候,就调用 strptime 将其转回 datetime 类型。
看下运行结果:
这样对于一些特殊类型的属性处理也得心应手了。
嵌套处理
最后我们再来看看嵌套类型的处理,比如类里面有个属性是另一个类的类型,如果遇到这种嵌套类的话,怎样类转转换呢?我们用一个实例感受下:
这里我们定义了两个 Class,一个是 Point,一个是 Color,然后定义了 Line 对象,其属性类型一个是 Color 类型,一个是 Point 类型组成的列表,下面我们进行序列化和反序列化操作,转成 JSON 然后再由 JSON 转回来,运行结果如下:
可以看到,我们非常方便地将对象转化为了 JSON 对象,然后也非常方便地转回了对象。
这样我们就成功实现了嵌套对象的序列化和反序列化,所有问题成功解决!
结语
本节介绍了利用 attrs 和 cattrs 两个库实现 Python 面向对象编程的实践,有了它们两个的加持,Python 面向对象编程不再是难事。
(*本文为 AI大本营转载文章,转载请联系原作者)
◆
精彩推荐
◆
大会开幕倒计时8天!
2019以太坊技术及应用大会特邀以太坊创始人V神与众多海内外知名技术专家齐聚北京,聚焦区块链技术,把握时代机遇,深耕行业应用,共话以太坊2.0新生态。即刻扫码,享优惠票价。
推荐阅读
真正的博士是如何参加AAAI, ICML, ICLR等AI顶会的?
Python最抢手、Java最流行、Go最有前途,7000位程序员揭秘2019软件开发现状
程序员学Python编程或许不知的十大提升工具
不要让 Chrome 成为下一个 IE!
这位博士跑赢“地震波”:提前 10 秒预警宜宾地震!
一张图告诉你到底学Python还是Java!
鸿蒙将至,安卓安否?
25岁创立加密城堡, 曾经独角兽创始人社会名流天才黑客是这里的沙发客, 如今却无人问津……
352万帧标注图片,1400个视频,亮风台推最大单目标跟踪数据集

相关文章:

mysql之 CentOS系统针对mysql参数优化
内核相关参数(/etc/sysctl.conf) 以下参数可以直接放到sysctl.conf文件的末尾: net.core.somaxconn 65535 net.core.netdev_max_backlog 65535 net.ipv4.tcp_max_syn_backlog 65535 加快TCP连接的回收: net.i…

天猫双十一神话恐终结
2011年双十一大促,天猫商城创造了单日33.6亿的促销奇迹,是2010年同日交易额的近4倍。今年双十一即将来临,淘宝还能再创奇迹吗?何玺认为,淘宝双十一的神话恐终结,理由如下。 一、电商促销年消费被透支 年初 …

opencv图像旋转
转自:http://download.csdn.net/source/2642701 /* 程序名:rotate.c 功能:读入图像文件,做图像旋转转,然后显示图像在屏幕上 */ #include <stdlib.h> #include <stdio.h> #include <math.h> #inclu…

机器如何读懂人心:Keras实现Self-Attention文本分类
作者 | 小宋是呢转载自CSDN博客一、Self-Attention概念详解了解了模型大致原理,我们可以详细的看一下究竟Self-Attention结构是怎样的。其基本结构如下对于self-attention来讲,Q(Query), K(Key), V(Value)三个矩阵均来自同一输入,首先我们要计…

通俗易懂!使用Excel和TF实现Transformer
作者 | 石晓文转载自小小挖掘机(ID:wAIsjwj)本文旨在通过最通俗易懂的过程来详解Transformer的每个步骤!假设我们在做一个从中文翻译到英文的过程,我们的词表很简单如下:中文词表:[机、器、学、习] 英文词表…

通过注册表修改VC6.0的字体【转】
2019独角兽企业重金招聘Python工程师标准>>> 在VC6.0下更改字体,我们一般通过菜单-Tools-Options-Format来更改 但在我的win7 64位系统下这一选项下的字体和字体颜色是空的,无法选择 所以我想起来通过注册表来更改。 WinR输入“Regedit”&…

Java中创建String的两种方式差异
我们知道创建一个String类型的变量一般有以下两种方法: String str1 "abcd"; String str2 new String("abcd"); 那么为什么会存在这两种创建方式呢,它们在内存中的表现形式各有什么区别? 方法1: String a …

OpenCV支持的图像格式
OpenCV目前支持的图像格式包括: Windows位图文件 - BMP, DIB; JPEG文件 - JPEG, JPG, JPE; 便携式网络图片 - PNG; 便携式图像格式 - PBM,PGM,PPM; Sun rasters - SR,RASÿ…

Debian Linux下的Python学习——控制流
python中有三种控制流语句:if、for和while。 1. if语句用法( if..elif..else) 代码: 运行: 注意:raw_input函数要求输入一个字符串,int把这个字符串转换为整数 2.for语句用法 (for ... else) 代码: 运行: 注:else部分是可选的。如果包含else,它总是在for循环结束后…

如何运行ImageMagick的命令行工具
在http://www.imagemagick.org/script/index.php网站下载相应的执行文件,这里以下载ImageMagick-6.6.5-10-Q16-windows-static.exe为例说明。 将ImageMagick-6.6.5-10-Q16-windows-static.exe下载后,安装,然后将其中需要的命令行工具考到你需…

华为最强自研NPU问世,麒麟810“抛弃”寒武纪
整理 | 一一出品 | AI科技大本营(ID:rgznai100)“能效高、算子多、精度高”,华为消费者业务手机产品线总裁何刚用一句话总结了自研达芬奇架构给最新麒麟810芯片带来的变化。6 月 21 日,在 HUAWEI Nova 5 系列新品发布会上&#x…
调用 微信接口报错 {errcode:48001,errmsg:api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]}...
如下截图,仅为备份,本文转载地址: http://www.cnblogs.com/liaolongjun/p/6080240.html 以下正文↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑…

javascript this用法小结
this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象。但是在javascript中,由于 javascript的动态性(解释执行,当然也有简单的预编译过程),this的指向在运…

在vc6控制台程序中如何调用运行ImageMagick命令行工具
在http://www.imagemagick.org/script/index.php网站下载相应的执行文件,这里以下载ImageMagick-6.6.5-10-Q16-windows-static.exe为例说明。 将ImageMagick-6.6.5-10-Q16-windows-static.exe下载后,安装,然后将其中需要的命令行工具考到你程…

高频数据交换下Flutter与ReactNative的对比
后端使用go写的socketio服务模拟期货行情数据,每10ms推送10条行情数据 ReactNative已经尽力优化了。 Flutter由于没flutter-socketio这个库不支持dart2.0以上的版本,所有用了安卓的socketio,通过事件与Flutter通讯。 1.内存占用 ReactNative …

6月技术福利限时免费领
《程序员大本营》6月刊来啦~更多福利限时免费领取:CSDN重磅技术大会精选视频以及200PPT;机器学习、知识图谱、计算机视觉、区块链等100技术公开课及PPT全奉送...识别海报二维码,邀请3位好友扫码助力,即可免费领取↓↓↓❤提示&…

我对bgwriter.c 与 guc 关系的初步理解
我用例子来说明:只是一个模拟,我自己做的 假的 bgwriter.c [rootlocalhost test]# cat bgwriter.c #include<stdio.h> #include<stdlib.h> #include<signal.h> #include "bgwriter.h" #include "guc.h" //some co…

媲美Pandas?一文入门Python的Datatable操作
作者 | Parul Pandey译者 | linstancy责编 | Jane出品 | Python大本营(id:pythonnews)【导读】工具包 datatable 的功能特征与 Pandas 非常类似,但更侧重于速度以及对大数据的支持。此外,datatable 还致力于实现更好的…

java并发编程——并发容器类介绍
2019独角兽企业重金招聘Python工程师标准>>> 并发容器的简单介绍 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能。因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性&a…

CV_IMAGE_ELEM参数赋值时注意的问题
转自:http://hi.baidu.com/wangruiy01/blog/item/041ab03e8abd33c57d1e71a0.html CV_IMAGE_ELEM是一个宏, #define CV_IMAGE_ELEM( image, elemtype, row, col ) /(((elemtype*)((image)->imageData (image)->widthStep*(row)))[(col)])#define …

公司内部exchange2010 下删除误发邮件
1、Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E20102、get-mailbox | search-mailbox -SearchQuery 填写误发邮件标题 -TargetMailbox "administrator" -TargetFolder "SearchAndDeleteLog" -DeleteContent转载于:https://blog.51cto.com/wo…

从代码设计到应用开发,入坑深度学习看这本书就够了
深度学习(Deep Learning)是机器学习中一种基于对数据进行表征学习的方法。近年来,深度学习已经在科技界、工业界日益广泛地应用。随着全球各领域多样化数据的极速积累和计算资源的成熟化商业服务,深度学习已经成为人工智能领域最有…

小波矩特征提取matlab代码
这是我上研究生时写的小波矩特征提取代码: %新归一化方法小波矩特征提取---------------------------------------------------------- Fimread(a1.bmp);Fim2bw(F);Fimresize(F,[128 128]);%求取最上点for i1:128 for j1:128 if (F(i,j)1) yt…

hadoop生态搭建(3节点)-06.hbase配置
# http://archive.apache.org/dist/hbase/1.2.4/ # 安装 hbase tar -zxvf ~/hbase-1.2.4-bin.tar.gz -C /usr/local rm –r ~/hbase-1.2.4-bin.tar.gz # 配置环境变量# node1 node2 node3 vi /etc/profile# 在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL下添…

异类框架BigDL,TensorFlow的潜在杀器!
作者 | Nandita Dwivedi译者 | 风车云马责编 | Jane出品 | AI 科技大本营(id:rgznai100)【导读】你能利用现有的 Spark 集群构建深度学习模型吗?如何分析存储在 HDFS、Hive 和 HBase 中 tb 级的数据吗?企业想用深度学习…

对IsUnderPostmaster变量初步学习
开始 在postmaster.c 中的 BackendStartup 中,有如下的代码: 其中定义了 IsUnderPostmastertrue。 而bgwriter 作为 postmaster 的子进程,它的 IsUnderPostmaster 也是为真。 * BackendStartup -- start backend process** returns: STATUS_…

C++读写ini配置文件GetPrivateProfileString()WritePrivateProfileString()
转自:http://hi.baidu.com/andywangcn/blog/item/10ba730f48160eeb37d122e9.html 配置文件中经常用到ini文件,在VC中其函数分别为: #include <Windows.h> //wince,WMobile.ppc不支持这几个函数 写入.ini文件:bool WritePriv…

地图下载2之天超图瓦片格式
接上一篇《地图下载1之天地图瓦片解析》,我们已经知道了天地图的瓦片格式,现在来分析一下超图中瓦片的存储结构。 其实,在GIS领域,只有像ESRI这样强大公司的SHP文件等能通用外,很多数据、格式等都不通用,都…

server 2003登录界面黑屏的解决办法
1、备份注册表(为了安全起见)具体办法:开始-> 运行窗口输入“regedit.exe”->回车->找到注册表->文件->导出->完成; 2、复制下面的文件内容到记事本然后另存为格式为.reg注册表扩展名导入注册表; Wi…

“学了半年后,我要揭开Python 3宗罪!”
有人曾说,未来只有2种人,会Python的人和....不懂Python的小学生,虽有夸张,这也意味着Python越来越重要了,究竟这门语言厉害在哪里?以下为你总结了Python3宗“罪”!Python凭啥这么优秀࿱…