ifove 发布于 2022-03-29 20:40:33来自
一.我们来好好研究一下“类”
1.Object 对象
学过java的朋友都清楚,在Java中,一切皆对象,是很纯正的面向对象语言,那么在python中呢?会不会也是这样呢?首先,不管是不是,我们先假设它是,然后去证明。如果在python中也是一切皆对象的话,那么一定有一个最原始的基类,就像Java中的Object一样,很容易的我们会猜想,会不会也是object的呢?我们通过交互命令来一看究竟:
果然,当我们通过 help 命令来查看的时候,发现了这些东西,首先这是一个 builtin 内置模块,其次,这是一个 most base 最顶层的基类,也就是说所有的类都继承自 object,最后,我们发现 object 类有很多内置属性,因此我们可以在我们的类中覆盖这些属性达到我们的目的。
在上面的这个例子中,我们调用了基类的 dir 和 str 方法,这里有一个问题,我们直接打印对象和我们调用基类的 str 结果是一样的,其实,当我们打印对象的时候,其自动调用__str__方法,不相信?我们再来一个例子,在这个例子中,我们覆盖__str__方法,看看打印对象之后产生什么结果。
其实,其他的内建对象,我们都可以去覆盖重写,这就取决于你要写的类的功能了。
2.类的方法
1.静态方法
静态方法可以直接被类或类实例调用。它没有常规方法那样的特殊行为(绑定、非绑定、默认的第一个参数规则等等)。完全可以将静态方法当成一个用属性引用方式调用的普通函数来看待。任何时候定义静态方法都不是必须的。我们看一下类的静态方法的定义:
静态方法的使用不必非得实例化(语言都是共通的),这点跟 Java 基本一样。
在类的静态方法中,我们要注意一个方法,new,当我们实例化一个类的时候,其实是类调用了__new__方法返回了一个类的对象,我们试试:
我们通过方法 isinstance 方法,来判断 Obj3 是否是 test 类的对象。但是,我们并不能直接通过__new__来获取对象,因为这个时候的 Obj3 仅仅只是个对象,可以简单的这么理解,那就是平常我们定义类的一个实例,其实是类先调用__new__生成对象,再来调用__init__进行初始化。我们验证一下:
2.类方法(非静态)
类的方法很简单,基本上和函数无异,只是有一个需要注意的地方,那就是必须明确的指出 self(其实与名称无关,只与位置有关,一般约定为 self),我们来看一下一段实例:
3.类的属性(Properties)
我们都知道,类中的属性,相当于成员变量,当我们在外部引用类的属性的时候,类是如何工作的呢?这个就要从__getattr__方法说起了,__getattr__是拦截属性点号运算,准确的说应该是,当通过对未定义的属性名称和实例进行点号运算时,就会用属性名称作为字符串调用这个方法,若可以通过 python 的继承树向上搜索不到这个属性,方法就不会调用,我们来看一段例子:
这个时候我们,肯定会想一件事情,那就是,我们可不可以改了 value 的打印结果呢?我想应该可以把,试试:
但是结果好像是不可以的,那该怎么办呢?我们来试试看另外一个方法__setattr__,该方法会拦截所有属性的赋值语句,如果定义了这个方法,self.attr = value 会变成 self.setattr(‘attr’,value)看一段代码:
但是,只要稍微心细一些就会发现,如果在__setattr__中对 self.value 进行赋值,就会陷入死循环,最后堆栈溢出异常,怎么解决呢?通常,我们是通过对属性字典做索引运算来赋值任何实例属性,也就是说,使用 self.dict[‘attrname’]=x,如下:
4.怎样表达类成员的“private”属性?
在 C++ 中,我们有 public protect private 那么,在 python 中如何实现属性,甚至是函数的私有化呢?这里就要用到__X__了,看一段代码:
属性和方法同理。