In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly shows you "Python programmers need to be able to use the library is what", the content is easy to understand, clear, hope to help you solve doubts, the following let the editor lead you to study and learn "Python programmers need to know how to use the library is what" this article.
This raises the question: is it troublesome to use classes in Python? Let's look at a simple data structure: a three-dimensional Cartesian coordinate. Start with the simplest:
Class Point3D (object):
So far so good. We already have a three-dimensional point. What's next?
Class Point3D (object): def _ _ init__ (self, x, y, z):
In fact, this is a bit of a pity. I just want to package the data, but I have to override a special method in the Python runtime, and the naming is conventional. But it's not so bad; after all, all programming languages are weird symbols in some form.
At least you can see the attribute name, which makes sense.
Class Point3D (object): def _ _ init__ (self, x, y, z): self.x
As I have said, I want an x, but now it must be specified as an attribute.
Class Point3D (object): def _ _ init__ (self, x, y, z): self.x = x
Bind to x? Well, it's obvious.
Class Point3D (object): def _ _ init__ (self, x, y, z): self.x = x self.y = y self.z = z
Every attribute has to do this once, so it's pretty bad? Each attribute name has to be typed three times.
Okay. At least it's defined.
Class Point3D (object): def _ init__ (self, x, y, z): self.x = x self.y = y self.z = z def _ repr__ (self):
What, it's not over yet?
Class Point3D (object): def _ init__ (self, x, y, z): self.x = x self.y = y self.z = z def _ repr__ (self): return (self.__class__.__name__ + ("(x = {}, y = {}, z = {})" .format (self.x, self.y, self.z)
Oh, please. Now I have to type the name of each property five times, if I want to know what the attribute means when debugging. If you define a tuple, you don't need this step.
Class Point3D (object): def _ init__ (self, x, y, z): self.x = x self.y = y self.z = z def _ repr__ (self): return (self.__class__.__name__ + ("(x = {}, y = {}, z = {})" .format (self.x, self.y) Self.z)) def _ eq__ (self, other): if not isinstance (other, self.__class__): return NotImplemented return (self.x, self.y, self.z) = (other.x, other.y, other.z)
Knock seven times?
Class Point3D (object): def _ init__ (self, x, y, z): self.x = x self.y = y self.z = z def _ repr__ (self): return (self.__class__.__name__ + ("(x = {}, y = {}, z = {})" .format (self.x, self.y) Self.z)) def _ eq__ (self, other): if not isinstance (other, self.__class__): return NotImplemented return (self.x, self.y, self.z) = (other.x, other.y, other.z) def _ lt__ (self, other): if not isinstance (other, self.__class__): return NotImplemented return (self.x Self.y, self.z)
< (other.x, other.y, other.z) 敲 9 次?!?!?!?!? from functools import total_ordering @total_ordering class Point3D(object): def __init__(self, x, y, z): self.x = x self.y = y self.z = z def __repr__(self): return (self.__class__.__name__ + ("(x={}, y={}, z={})".format(self.x, self.y, self.z))) def __eq__(self, other): if not isinstance(other, self.__class__): return NotImplemented return (self.x, self.y, self.z) == (other.x, other.y, other.z) def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented return (self.x, self.y, self.z) < (other.x, other.y, other.z) 好了,擦汗 - 尽管多了 2 行代码不是很好,但至少现在我们不用定义其他比较方法了。现在一切搞定了,对吧? from unittest import TestCase class Point3DTests(TestCase): 你知道吗? 我受够了。一个类码了 20 行,却还什么事都没做;我们这样做是想解四元方程,而不是定义"可以打印和比较的数据结构"。我陷入了大量无用的垃圾元组、列表和字典中;用 Python 定义合适的数据结构是非常麻烦的。 命名元组 namedtuple 为解决这个难题,标准库给出的解决方案是使用 namedtuple 。然而不幸的是初稿(在许多方面与我自己的处理方式有相似的尴尬的和过时之处)namedtuple 仍然无法挽救这个现象。它引入了大量没有必要的公共函数,这对于兼容性维护来说简直就是一场噩梦,并且它连问题的一半都没有解决。这种做法的缺陷太多了,这里只列一些重点: 不管你是否希望如此,它的字段都可以通过数字索引的方式访问。这意味你不能有私有属性,因为所有属性通过公开的 __getitem__ 接口暴露出来。 它等同于有相同值的原始元组,因此很容易发生类型混乱,特别是如果你想避免使用元组和列表。 这是一个元组,所以它总是不可变的。 至于***一点,你可以像这样使用: Point3D = namedtuple('Point3D', ['x', 'y', 'z']) 在这种情况下它看起来并不像一种类;无特殊情况下,简单的语法分析工具将不能识别它为类。但是这样你不能给它添加任何其他方法,因为没有地方放任何的方法。更别提你必须输入类的名字两次。 或者你可以使用继承: class Point3D(namedtuple('_Point3DBase', 'x y z'.split())): pass 尽管这样可以添加方法和文档字符串,看起来也像一个类,但是内部名称(在 repr 中显示的内容,并不是类的真实名称)变的很怪了。同时,你还不知不觉中把没列出的属性变成了可变的,这是添加 class 声明的一个奇怪的副作用;除非你在类主体中添加 __slots__='X Y z'.split(),但这样又回到了每个属性名必须敲两次的情况。 而且,我们还没提科学已经证明不应该使用继承呢。 因此,如果你只能选命名元组,那就选命名元组吧,也算是改进,虽然只是在部分情况下如此。 使用 attrs 这时该我最喜欢的 Python 库出场了。 pip install attrs 我们重新审视一下上述问题。如何使用 attrs 库编写 Point3D ? import attr @attr.s 由于它还没有内置到 Python 中,所以必须用以上 2 行开始:导入包然后使用类装饰器。 import attr @attr.s class Point3D(object): 你看,没有继承!通过使用类装饰器,Point3D 仍然是一个普通的 Python 类(尽管我们一会会看到一些双下划线方法)。 import attr @attr.s class Point3D(object): x = attr.ib() 添加属性 x。 import attr @attr.s class Point3D(object): x = attr.ib() y = attr.ib() z = attr.ib() 再分别添加属性 y 和 z。这样就完成了。 这就 OK 了? 等等。不用定义字符串表示吗? >> Point3D (1,2,3) Point3D (xylene 1, yellow2, zonal 3)
How to compare?
> > Point3D (1,2,3) = = Point3D (1,2,3) True > Point3D (3,2,1) = = Point3D (1,2,3) False > Point3D (3,2,3) > Point3D (1,2,3) True
Yes. But what if I want to extract data with well-defined attributes into a format suitable for JSON serialization?
> attr.asdict (Point3D (1,2,3)) {'Yee: 2,' x: 1,'z: 3}
Maybe it's a little accurate. Even so, a lot of things are easier with attrs, which allows you to declare fields and related metadata on your classes.
Pprint > > pprint.pprint (attr.fields (Point3D)) (Attribute (name='x', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None), Attribute (name='y', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None), Attribute (name='z', default=NOTHING, validator=None, repr=True, cmp=True, hash=True, init=True, convert=None))
I'm not going to delve into every interesting feature of attrs here; you can read its documentation. In addition, the project will be updated frequently, and something new will appear every once in a while, so I may miss some important features. But with attrs, you'll find what it did that Python lacked before:
It lets you define types succinctly, rather than by manually typing def _ _ init _ _.
It allows you to say what you mean directly instead of expressing it in a roundabout way. Instead of saying, "I have a type, which is called MyType, and it has a constructor that assigns the property'A' in the constructor with the parameter'A'," instead of saying, "I have a type, it's called MyType, it has a property called a, and the methods associated with it," instead of having to guess its method through reverse engineering (for example, running dir in an instance Or view self.__ class__. _ _ dict__).
It provides a useful default method, unlike the default behavior in Python, which is sometimes useful and most of the time useless.
It starts with simplicity, but provides room to add more rigorous implementations later.
Let's elaborate on one point.
Gradual improvement
Although I'm not going to talk about every feature, I would be irresponsible if I didn't mention the following features. You can see some interesting things in these very long Attribute repr () above.
For example, you validate attributes by decorating the class with @ attr.s. For example, the class Point3D should contain numbers. For simplicity, we can say that these numbers are of type float, like this:
Import attr from attr.validators import instance_of @ attr.s class Point3D (object): X = attr.ib (validator=instance_of (float)) y = attr.ib (validator=instance_of (float)) z = attr.ib (validator=instance_of (float))
Because we use attrs, this means that we have a chance to validate later: you can just add type information to each required attribute. Some of these features allow us to avoid common mistakes. For example, this is a very common "find Bug" interview question:
Class Bag: def _ init__ (self, contents= []): self._contents = contents def add (self, something): self._contents.append (something) def get (self): return self._contents [:]
Fix it, and the correct code should look like this:
Class Bag: def _ _ init__ (self, contents=None): if contents is None: contents= [] self._contents = contents
Two additional lines of code have been added.
In this way, contents inadvertently becomes a global variable, which makes all Bag objects that do not provide a list share a list. If you use attrs, it looks like this:
Attr.s class Bag: _ contents = attr.ib (default=attr.Factory (list)) def add (self, something): self._contents.append (something) def get (self): return self._contents [:]
Attrs also provides some other features that make it easier and more correct for you to build classes. Another good example? If you strictly control the properties of an object (or CPython, which is more efficient in memory use), you can use slots=True at the class level-for example, @ attr.s (slots=True)-to automatically match the _ _ slots__ attribute declared by attrs. All of these features make the properties declared through attr.ib () better and more powerful.
Future Python
Some people are happy that Python 3 programming will be widely used in the future. What I'm looking forward to is being able to program with Python all the time with attrs. As far as I know, it has a positive and subtle impact on every code base used.
Give it a try: you may be surprised to find that classes with clear explanations can now be used where tuples, lists, or dictionaries that are not convenient for writing documents are available. Since writing well-structured types is so easy and convenient, you should often use attrs in the future.
The above is all the content of the article "what Python programmers need to know how to use libraries". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.