Python3 学习第五弹:类与面向对象
对于面向对象总是要提到,万物皆对象。好似博大精深的感觉。
接下来一起看看python的面向对象的例子
创建一个对象
class Person:
type = 'person'
def __init__(self, name = 'Noname'):
self.name = name
def hello(self):
print("hello, I'm " + self.name)
>>> Mike = Person('Mike')
>>> Mike.hello()
hello, I'm Mike
对于一个对象,均会有默认构造方法,当然我们可以通过重写__init__来改变构造方法。当一个对象创建时会自动调用构造方法。
类的属性
对于上一例的类来说
其类属性:type以及默认类属性
实例属性:name
很容易理解,实例属性只有当创建一个类对象时才会产生,而类属性是类固有的属性
类属性访问可以通过dir(Person)或Person.__dict__查看
而实例属性可以通过Mike.__dict__查看 基本类属性:
__doc__ 函式的文档. 字符串, 如果没有 的话就为 None 可写
__name__ 函式名 可写
__module__ 定义函式的模块名, 或者如果没有 对应模块名, 就为 None
__bases__ 返回该类的所有父类构成的元组
__class__ 实例所对应的类
__dict__ 类的属性构成的字典 >>> class Person:
'''Michael Scofield's file'''
name = 'Michael'
def __init__(self, age):
self.age = age
>>> Person.__doc__
"Michael Scofield's file"
>>> Person.__name__
'Person'
>>> Person.__bases__
(<class 'object'>,)
>>> Person.__dict__
mappingproxy({'__dict__': <attribute '__dict__' of 'Person' objects>, '__doc__': "Michael Scofield's file", '__weakref__': <attribute '__weakref__' of 'Person' objects>, 'name': 'Michael', '__module__': '__main__', '__init__': <function Person.__init__ at 0x00000000033DBBF8>})
>>> a = Person(30)
>>> a.__class__
<class '__main__.Person'>
继承的应用
子类可以通过继承来获得父类的属性,此外可以有自己的类属性
>>> class Bird:
def __init__(self):
self.hungry = True
def eat(self):
if self.hungry:
print('eat something')
self.hungry = False
else:
print('Too fat')
>>> class SongBird(Bird):
def __init__(self, song):
self.song = song
def sing(self):
print(self.song)
>>> a = SongBird('hello')
>>> a.sing()
hello
我们常常会遇到子类有父类的相似函数,但是又不太一样。就可以通过重写来建立自己的函数,在运行该函数的时候会先在子类中找该函数,若无再从父类中寻找,例如上例中的__init__方法重写
但是又会出现一个问题,
>>> a.eat()
AttributeError: 'SongBird' object has no attribute 'hungry'
由于没有调用到父类的init使得hungry的属性消失,这时候利用super可以消除这种影响。
>>> class SongBird(Bird):
def __init__(self, song):
super(SongBird, self).__init__()
self.song = song
>>> a.eat()
eat something
>>> a.eat()
Too fat
这里的super不是一个函数,而是一个类,表示SongBird的父类并传入自身对象self
当然在出现super之前有另一个解决办法,就是直接调用父类的函数
>>> class SongBird(Bird):
def __init__(self, song):
Bird.__init__(self)
self.song = song
但是由于一旦改动其父类,需要每次改变该类中的父类如上例中的Bird,因此最好使用super
通过property函数对类进行封装
>>> class rec:
def __init__(self):
self.width = 0
self.height = 0
def setSize(self, sz):
self.width = self.height = sz
def getSize(self):
return self.width, self.height
size = property(getSize, setSize)
>>> r = rec()
>>> r.size
(0, 0)
>>> r.size = 1
>>> r.size
(1, 1)
>>> r.width = 2
>>> r.size
(2, 1) 先看看这样的描述更符合一种封装的思想,不必去在意其中实现的方法,只看重结果。
那么是如何实现的呢?
property(fget, fset, fdel, doc)可以通过4种参数来调用相应的过程,其中所所涉及的方法就是前面__get__,__set__,__delete__三种方法,实现了其中任何一种方法的对象就叫做描述符(descriptor)。
就像上面的例子getSize实现了__get__方法,也就是在每次调用size时,对size取值都会调用到__get__方法,运行getSize函数
举个例子,如果r是rec的一个类对象,那么r.size会调用__get__方法(getter),r.size = value会调用__set__方法(setter),del r.size会调用__delete__方法(deleter)。 另外property封装的办法就是通过@进行一种类似装饰器描述 class C:
def __init__(self):
self._x = None @property #定义属性x,生成__get__方法
def x(self):
"""I'm the 'x' property."""
return self._x @x.setter #生成__set__方法
def x(self, value):
self._x = value @x.deleter #生成__delete__方法
def x(self):
del self._x 需要说明的是,属性x名称可以任意改变,而且用法与上一例的size相同。但要保证属性x名称相同,而且定义函数名均用属性名表示
类方法(类似于操作符重载)
像上面例子中的__init__就是构造方法,当创建一个新类对象时自动调用,此外,还有许多可供使用的类方法,几乎覆盖了python所有操作符。
接下来我们来看一看常见的类方法。 >>基本方法: 1> __init__(self[, arg1, ...]) 构造函数,在函数对象创建后调用,无返回值 2> __new__(self[, arg1, ...]) 构造函数,创建函数对象的函数,返回值即该对象
一般来说__new__不会被用到,除非子类需要不可变类型时才会用到。 3> __del__(self) 在对象删除时调用,一般不改变,因为对象删除的时间由python自身决定 4> __str__(self) 返回要打印的字符串(对用户较为友好),内建有str()及print 5> __repr__(self) 返回对编译器友好的字符串,对细节处理上略有不同 repr 与 str 区别:
The str() function is meant to return representations of values which are fairly human-readable, while repr() is meant to generate representations which can be read by the interpreter (or will force a SyntaxError if there is not equivalent syntax). For objects which don't have a particular representation for human consumption, str() will return the same value as repr(). Many values, such as numbers or structures like lists and dictionaries, have the same representation using either function. Strings and floating point numbers, in particular, have two distinct representations. 6> __format__(self, format_spec) 调用format()运行该函数 7> __call__(self, *args) 类可以当作函数来调用,每次调用这个类对象时会运行,相当于重载了括号 8> __len__(self) 在调用len()时会运行会运行该函数 >>比较方法: 1> __lt__(self, obj) 重载 < 2> __le__(self, obj) 重载 <= 3> __eq__(self, obj) 重载 == 4> __ne__(self, obj) 重载 != 5> __gt__(self, obj) 重载 > 6> __ge__(self, obj) 重载 >= 其中若不重载>, >默认会与<的对象交换,反之相同 >>> class Person:
def __init__(self, age):
self.age = age
def __lt__(self, b):
return self.age - b.age
def __gt__(self, b):
return self.age > b.age
>>> a = Person(1)
>>> b = Person(2)
>>> a > b
False
>>> a < b
-1
>>> b > a
True
>>> b < a
1 >>属性操作方法
(注意以下的attr属性都是用字符串表示) 1> __getattr__(self, attr) 获取属性不成功时调用,使用getattr()时调用(很奇怪在用python3测试时,即使获取属性成功也调用了) 2> __setattr__(self, attr, value) 设置属性或新建属性时调用,使用setattr()时调用 >>> class Person:
def __init__(self, age):
self.age = age
def __getattr__(self, attr):
print('__getattr__ used')
def __setattr__(self, attr, val):
print('__setattr__ used')
>>> a = Person(1)
__setattr__ used
>>> a.age
__getattr__ used
>>> a.age=1
__setattr__ used 3> __delattr__(self, attr) 删除属性,使用delattr()调用 4> __getattribute__(self, attr) 获取属性时无论访问成功与否都调用 5> __get__(self, attr) 描述器,获取属性
6> __set__(self, attr, value) 描述器,设置属性
7> __delete__(self, attr) 描述器 删除属性
以上三个暂时不明白其用法 >> 数值运算符号重载 1> __add__(self, other) 重载+
2> __sub__(self, other) 重载-
3> __mul__(self, other) 重载*
4> __truediv__(self, other) 重载/
5> __floordiv__(self, other) 重载//
6> __mod__(self, other) 重载%
7> __divmod__(self, other) 重载divmod(a, b) #返回元组(a//b, a%b)
8> __pow__(self, other[, modulo]) 重载pow(a, b) **
9> __lshift__(self, other) 重载<<
10> __rshift__(self, other) 重载>>
11> __and__(self, other) 重载&
12> __xor__(self, other) 重载^
13> __or__(self, other) 重载| ADD1:
若在上述重载计算操作符函数前加入r,即__radd__(self, other),则表示其参数位置对调。
例如, 计算表达式 x - y, y 是一个定义了方法 __rsub__() 的类实例, 那么在 x.__sub__(y) 返回 NotImplemented 时才会调用 y.__rsub__(x).
ADD2:
若在上述重载计算操作符函数前加入i,即__iadd__(self, other),则该重载符为 += 。以此类推 14> __neg__(self) 重载负号-
15> __pos__(self) 重载正号+
16> __abs__(self) 重载abs()
17> __invert__(self) 重载^ 强制转换类型
18> __complex__(self) 重载complex() #表示复数类型
19> __int__(self) 重载int()
20> __float__(self) 重载float()
21> __round__(self) 重载round() >>序列操作符重载 1> __len__(self) 序列中项的个数 2> __getitem__(self, index) 获取序列时调用 3> __setitem__(self, index, value) 设置序列项或者新建项时调用 4> __delitem__(self, index) 删除单个序列元素时调用 >>> class Class:
def __init__(self):
self.student = ['LWT', 'CYL', 'Bash']
def __len__(self):
print('len called')
return len(self.student)
def __getitem__(self, index):
print('getitem called')
return self.student[index]
def __setitem__(self, index, value):
print('setitem called')
self.student[index] = value
def __delitem__(self, index):
print('delitem called')
del self.student[index]
>>> a609 = Class()
>>> len(a609)
len called
3
>>> a609[1]
getitem called
'CYL'
>>> a609[2] = 'Bug'
setitem called
>>> a609
<__main__.Class object at 0x0000000003C3FD30>
>>> del a609[2]
delitem called 其实就相当于对列表进行重载其操作。 以上,大概包括了大部分的重载类型。
Python3 学习第五弹:类与面向对象的更多相关文章
- 前端学习 第五弹: CSS (一)
前端学习 第五弹: CSS (一) 创建css: <link rel="stylesheet" type="text/css" href="my ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- Python3 学习第十三弹: 模块学习五之pickle与json
对于python来说,这两个模块是十分实用的两个模块,以一种简单的方法用于储存数据实例. pickle模块 提供用来储存Python各种数据序列化存储 # 原来的cPickle已经在python3中与 ...
- JAVA学习(五):Java面向对象编程基础
Java面向对象编程基础 面向对象(Object oriented programming,OOP)技术是一种强有力的软件开发方法,它採用数据抽象与信息隐藏技术,来使软件开发简单化,以达到代码重用的目 ...
- Python3 学习第八弹: 模块学习一之模块变量
__name__变量 用于判断该python文件是否作为主程序运行.若该文件为导入,__name__值为其文件名,若为主程序,则其值为__main__ 这也就是为什么经常看到有一些python文件中有 ...
- Python3 学习第六弹: 迭代器与生成器
1> 迭代器 迭代的意思类似递归一般,不断地对一个对象做重复的操作.来看个例子: class Fibs: def __init__(self): self.last = self.now = 1 ...
- Python3 学习第四弹:编码问题(转载)
关于python的编码问题一直以来不得解,终于在今天从这篇博文中明白了. 原文地址: http://nedbatchelder.com/text/unipain.html 译文地址:http://py ...
- Python3 学习第三弹:异常情况如何处理?
python 的处理错误的方式: 1> 断言 assert condition 相当于 if not condition: crash program 断言设置的目的就是因为与其让程序晚点崩溃, ...
随机推荐
- 实现WMSservice的时候,出现边缘的点或icon被切断的情况
可以通过为实际查询的boundary加一个buffer,使查询的范围比指定的大一点点,这样就会使tile之间在查询的时候有一定的重叠. 如:Geometry queryBoundary = JTS.t ...
- mysql 数据库优化
提到优化,先要确定出现的问题,是存储引擎选择问题,还是sql语句使用问题(如:索引)亦或者是单一存储服务器对于千万级别的数据力不从心. 解决方法:1.根据不同业务选用不同存储引擎,虽然一般情况下都优先 ...
- javascript实现数据结构:线性表--线性链表(链式存储结构)
上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...
- DirectShow学习笔记
DirectShow, as you might have guessed, is a COM based multimedia framework that makes the task of ca ...
- DELPHI 获取本月 的第一天 和 最后一天
USER :DateUtils 使用 StartOfTheMonth 和 EndOfTheMonth 函数获取即可: procedure TForm1.btn1Click(Sender: TObj ...
- POJ 2480 Longge's problem (积性函数,欧拉函数)
题意:求∑gcd(i,n),1<=i<=n思路:f(n)=∑gcd(i,n),1<=i<=n可以知道,其实f(n)=sum(p*φ(n/p)),其中p是n的因子.为什么呢?原因 ...
- POJ 1679 The Unique MST(次小生成树)
题意:求解最小生成树的权值是否唯一,即要我们求次小生成树的权值两种方法求最小生成树,一种用prim算法, 一种用kruskal算法 一:用prim算法 对于给定的图,我们可以证明,次小生成树可以由最小 ...
- C# 枚举类型操作
//定义一个枚举 public enum Colors { Red, Green, Blue, Yellow }; //根据key找value string name = Enum.GetName(t ...
- hdu 4462(状态压缩)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4462 思路:由于数据不大,可以直接将所有的状态表示出来,然后枚举,判断能否将方格全部覆盖. http: ...
- hdu 3118(二进制枚举)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3118 思路:题目要求是去掉最少的边使得图中不存在路径长度为奇数的环,这个问题等价于在图中去掉若干条边, ...