Python面向对象编程基础实例分析


Posted in Python onJanuary 17, 2020

本文实例讲述了Python面向对象编程基础。分享给大家供大家参考,具体如下:

1、类的定义

Python中类的定义与对象的初始化如下,python中所有类的父类是object,需要继承。

由于Python是动态语言,因此可以直接为对象添加属性并赋值而不必在类定义中声明

class Person(object):  # 定义一个Person类
  pass
p = Person()  # 初始化一个Person对象
p.name="xiaoming"  # 对象属性赋值

Python的类初始化方法为__init__(),其第一个参数为self代之对象自身,其后为各个参数,初始化就是将传入的参数赋值给对象的属性。**kw代表任意数量的属性,通过key=attribute的形式传入,之后通过setattr()方法将每个属性赋值给对象。

直接在class中定义的变量称为类属性,在__init__()中定义的为对象属性,类属性供所有对象共享,对象只能访问却无权修改。当通过对象给类属性赋值时,会为对象新建一个同名的对象属性,而不是修改类属性。无论在类的内部还是外部,都通过类名对类属性进行访问。

以__开头的变量无法被外部访问,类似于私有变量。这时就需要对象的实例方法从类的内部访问私有变量并做出相应的操作,这样在类的内部定义的方法叫做实例方法,实例方法的第一个参数默认为self代表对象自己。

相应地类方法只能访问类属性,其定义方式是在之前添加标记@classmethod:,其第一个参数cls代表类本身

class Person(object):
  count = 0  # 类属性
  @classmethod:
  def get_count(cls):  # 类方法
    return cls.count
  def __init__(self,name,gender,birth,**kw):
    Person.count+=1  # 访问类属性
    self.name = name
    self.__gender = gender
    self.birth = birth
    for k, v in kw.iteritems():  # 遍历之后的键值对,设置属性
      setattr(self, k, v)
  def get_name(self):  # 定义实例方法
    return self.__name
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
xiaoming.count==9  # 为对象创建属性,不会修改Person.count
print(xiaoming.job)  # 显示Student
print(xiaoming.__gender)  # 无法访问,抛出异常AttributeError
print(xiaoming.get_name())  # 通过实例方法访问内部变量

2、类的继承

Python中类的继承方式如下。值得注意的是在子类Teacher中需要通过super(子类名,self)调用父类的初始化函数来完成对父类中参数的初始化。也可以直接通过父类名称调用父类的方法

通过type()方法输出变量的类型,isinstance()可以判断变量是否是某个类型,dir()方法返回变量的所有属性和方法列表。输出对象t的属性结果如下,其中带__的为默认属性,其余为自定义的属性

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'course', 'gender', 'name']

class Person(object):
  def __init__(self, name, gender):
    self.name = name
    self.gender = gender
class Teacher(Person):  # 继承父类Person
  def __init__(self, name, gender, course):
    super(Teacher,self).__init__(name,gender)  # 调用父类的初始化函数
    self.course= course  # 完成子类变量的初始化
t = Teacher('Alice', 'Female', 'English')
print(isinstance(t,Person))  # 结果为True,子类也是父类的类型
print(dir(t))  # 显示对象的所有属性

和其他面向对象的语言一样,Python具有多态的特性,例如父类和不同的子类都定义了相同的方法,当不同的子类调用该方法时会调用自己定义的方法,从而实现相同的方法具有不同的操作。但python是动态语言,和静态语言C++、Java不同的是在调用实例方法时,python不检查类型,只要方法存在,参数正确,就可以调用。例如原本json的load方法中定义了read()方法用于实现对文件的读取,当我们自定义一个类其中包含read()方法时,便可动态调用实例方法

import json
class Students(object):
  def read(self):
    return r'["Tim", "Bob", "Alice"]'
s = Students()
print json.load(s)

一个子类可以同时继承两个以上的父类,这个特性叫做多继承,当有多个父类时,需要在初始化时指明父类

class A(object):
  def __init__(self, a):
    self.a = a
class B(object):
  def __init__(self, b):
    self.b = b
class C(A, B):
  def __init__(self, a, b, c):
    A.__init__(self, a)
    B.__init__(self, b)
    self.c = c
c = C(1, 2, 3)
print(c.a)   # 输出1

3、类的特殊方法

Python的特殊方法是指定义在类中,以__开头和结尾,由某些函数或操作符隐式触发调用的方法。例如当我们使用print(p)打印一个Person对象p时,就会调用Person的__str__()方法将p转化为字符串共print输出,输出结果为:<__main__.Person object at 0x000001787CC7C0D0>

当我们重新自定义这些特殊方法后,当触发调用时就会按我们定义的函数执行。例如重新定义__str__(),当print()时就会显示My name is Bob

class Person(object):
  def __init__(self, name, gender):
    self.name = name
    self.gender = gender
  def __str__(self):  # 重新定义类特殊方法
    return "My name is " + self.name
p = Person('Bob', 'male')
print(p)  # 输出结果为:My name is Bob

__cmp__()方法用于实现类的比较,在排序时会自动调用。例如在Student类中重新定义该方法,按分数高低对学生进行排序,其有两个参数,第一个自己self,第二个是比较的对象s,如果self应该在s之前,则返回-1

class Student(object):
  def __init__(self, name, score):
    self.name = name
    self.score = score
  def __cmp__(self, s):  # 重写__cmp__方法
    if self.score>s.score:
      return -1  # self在s之前
    elif self.score<s.score:
      return 1
    else:
      return 0
L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]
Ls = sorted(L)  # 使用sorted对Student类进行排序

__len__()方法用于返回长度,当len()调用类时会触发

__add__、__sub__、__mul__、__div__分别对应类的加减乘除运算,当类遇到运算符+-*/时会调用该方法,例如实现一个分数类Rational的加法:1/2+1/4,通分相加得6/8,最后求最大公约数后约分得到3/4

__int__、__float__方法在int()、float()调用类时触发,可以重新该方法返回一个int或float结果

def gcd(a, b):  # 求最大公约数
  if b == 0:
    return a
  return gcd(b, a % b)
class Rational(object):
  def __init__(self, p, q):
    self.p = p
    self.q = q
  def __add__(self, r):  # 重写加法运算
    return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
  def __str__(self):
    g = gcd(self.p, self.q)  # 将分数约分后输出
    return '%s/%s' % (self.p / g, self.q / g)
  def __float__(self):  # 将分数转化为float小数返回
    return float(self.p)/float(self.q)
r1 = Rational(1, 2)
r2 = Rational(1, 4)
print(r1 + r2)  # 两个类相加
print(float(r1))  # 输出小数形式

类属性的装饰器@property用于将类方法转化为属性,这样就可以像访问属性一样调用方法。例如Student类的__score属性对外是不可见的,通过定义返回方法score使得对象s可以通过s.score得到分数值。

@property.setter方法用于对属性设置方法进行装饰,使得可以像给属性赋值一样调用类方法。例如当使用s.score=99时会调用设置方法score(self,score),将值传递给__score,并且可以对传入值的合法性进行检验。

__slots__()用于定义类中可以使用的属性,父类定义过的子类中无需重复定义。当添加新的属性并赋值时,运行会抛出异常AttributeError

__call__()将一个类实例变成一个可调用对象,例如一个Student对象s,像函数调用一样使用对象:s('Alice')

class Student(object):
  __slots__ = ('name','__score')  # 本类只允许使用name、score两个属性
  def __init__(self, name, score):
    self.name = name
    self.__score = score
  @property        # 定义属性返回方法
  def score(self):
    return self.__score
  @score.setter      # 定义属性设置方法
  def score(self, score):
    if score < 0 or score > 100:
      raise ValueError('invalid score')
    self.__score = score
  def __call__(self, friend):
    print('My friend is %s...' % friend)
s = Student('Bob', 59)
s.score = 60  # 调用属性设置方法
print(s.score)  # 调用属性返回方法
s.grade='A'  # 抛出异常,无法添加其他属性
s('Alice')  # 输出My friend is Alice...

__getattribute__(self,attr)、__setattr__(self,attr)、__delattr__(self,attr)分别用于获取、设置、删除属性时触发的方法,在使用时应注意避免递归调用引起的无限循环,例如在get方法中再调用get类似的方法导致无限循环。

4、模块管理

为了方便分类管理python中的类和方法,需要将代码放在不同的文件中,每个文件构成了一个独立的模块,不同模块之间相同的变量名不会引起命名冲突。但是如果在文件a.py中希望使用文件b.py中的函数func1,则可以通过import在a中导入模块b,并通过b.func1()调用该方法。或者通过from直接引入模块中的函数。在引入时为了防止命名冲突,可以通过as为引入的函数起个别名

# 文件a.py中
import b
print(b.func1())
# 直接引入函数
from b import func1
print(func1())
# 使用别名
from b import func1 as f1
print(f1())

有时将相同类别的模块放在一个文件夹内,就形成了一个包,python要求一个包文件夹内必须有一个__init__.py文件才会识别为一个包,即使它是一个空文件。这时如果一个p1包内的a.py想访问p2包内的b.py中的函数func2,则操作如下

# p1/a.py文件内
import p2.b
print (p2.b.func2())

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python中为什么要用self探讨
Apr 14 Python
使用C++扩展Python的功能详解
Jan 12 Python
对Python中9种生成新对象的方法总结
May 23 Python
matplotlib 输出保存指定尺寸的图片方法
May 24 Python
python进阶之多线程对同一个全局变量的处理方法
Nov 09 Python
python如何给字典的键对应的值为字典项的字典赋值
Jul 05 Python
python爬虫 urllib模块url编码处理详解
Aug 20 Python
如何通过Django使用本地css/js文件
Jan 20 Python
Python连接SQLite数据库并进行增册改查操作方法详解
Feb 18 Python
详解pandas绘制矩阵散点图(scatter_matrix)的方法
Apr 23 Python
Python Selenium自动化获取页面信息的方法
Aug 31 Python
详解python的内存分配机制
May 10 Python
通过python实现windows桌面截图代码实例
Jan 17 #Python
PyTorch加载预训练模型实例(pretrained)
Jan 17 #Python
python 正则表达式参数替换实例详解
Jan 17 #Python
Python函数式编程实例详解
Jan 17 #Python
python实现tail -f 功能
Jan 17 #Python
解决Python命令行下退格,删除,方向键乱码(亲测有效)
Jan 16 #Python
python对象销毁实例(垃圾回收)
Jan 16 #Python
You might like
PHP base64编码后解码乱码的解决办法
2014/06/19 PHP
php在线解压ZIP文件的方法
2014/12/30 PHP
jquery 笔记 事件
2011/11/02 Javascript
jqTransform form表单美化插件使用方法
2012/07/05 Javascript
nodejs npm包管理的配置方法及常用命令介绍
2014/06/05 NodeJs
Jquery实现动态切换图片的方法
2015/05/18 Javascript
省市区三级联动下拉框菜单javascript版
2015/08/11 Javascript
node模块机制与异步处理详解
2016/03/13 Javascript
Angular2 (RC4) 路由与导航详解
2016/09/21 Javascript
微信小程序  modal弹框组件详解
2016/10/27 Javascript
Bootstrap模态窗口源码解析
2017/02/08 Javascript
详解vue.js移动端导航navigationbar的封装
2017/07/05 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
JS实现图片切换效果
2018/11/17 Javascript
vue组件三大核心概念图文详解
2019/05/30 Javascript
EasyUI 数据表格datagrid列自适应内容宽度的实现
2019/07/18 Javascript
[02:23]1个至宝=115个英雄特效 最“绿”至宝拉比克“魔导师密钥”登场
2018/12/29 DOTA
Python实现批量修改文件名实例
2015/07/08 Python
Python调用C# Com dll组件实战教程
2017/10/12 Python
python八大排序算法速度实例对比
2017/12/06 Python
PyQt5 在label显示的图片中绘制矩形的方法
2019/06/17 Python
python程序快速缩进多行代码方法总结
2019/06/23 Python
Python代码使用 Pyftpdlib实现FTP服务器功能
2019/07/22 Python
Pycharm+Python+PyQt5使用详解
2019/09/25 Python
python opencv 实现对图像边缘扩充
2020/01/19 Python
文明礼仪事迹材料
2014/01/09 职场文书
大学学习生活感言
2014/01/18 职场文书
会计专业个人自我鉴定
2014/03/21 职场文书
毕业晚会主持词
2014/03/24 职场文书
小学生国旗下演讲稿
2014/04/25 职场文书
大队干部竞选演讲稿
2014/04/28 职场文书
十佳家长事迹材料
2014/08/26 职场文书
万能检讨书2000字
2014/10/17 职场文书
小程序实现筛子抽奖
2021/05/26 Javascript
用React Native制作一个简单的游戏引擎
2021/05/27 Javascript
解决mysql问题:由于找不到MSVCR120.dll,无法继续执行代码
2021/06/26 MySQL