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编程对列表中字典元素进行排序的方法详解
May 26 Python
老生常谈python之鸭子类和多态
Jun 13 Python
Python cookbook(数据结构与算法)实现对不原生支持比较操作的对象排序算法示例
Mar 15 Python
实用自动化运维Python脚本分享
Jun 04 Python
Python中pandas模块DataFrame创建方法示例
Jun 20 Python
python多线程调用exit无法退出的解决方法
Feb 18 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
May 15 Python
Django获取该数据的上一条和下一条方法
Aug 12 Python
Python实现多线程/多进程的TCP服务器
Sep 03 Python
从训练好的tensorflow模型中打印训练变量实例
Jan 20 Python
使用keras和tensorflow保存为可部署的pb格式
May 25 Python
python中watchdog文件监控与检测上传功能
Oct 30 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设计模式 注册表模式(多个类的注册)
2012/02/05 PHP
一款js和css代码压缩工具[附JAVA环境配置方法]
2010/04/16 Javascript
从零开始学习jQuery (二) 万能的选择器
2010/10/01 Javascript
js函数返回多个返回值的示例代码
2013/11/05 Javascript
jQuery层级选择器用法分析
2015/02/10 Javascript
JavaScript事件类型中焦点、鼠标和滚轮事件详解
2016/01/25 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
2016/06/12 Javascript
浅谈js中调用函数时加不加括号的问题
2016/07/28 Javascript
jQuery实现的简单拖拽功能示例
2016/09/13 Javascript
JS点击缩略图整屏居中放大图片效果
2017/07/04 Javascript
JavaScript 完成注册页面表单校验的实例
2017/08/19 Javascript
JS动态添加的div点击跳转到另一页面实现代码
2017/09/30 Javascript
js实现消灭星星(web简易版)
2020/03/24 Javascript
vue实现户籍管理系统
2020/05/29 Javascript
移动端JS实现拖拽两种方法解析
2020/10/12 Javascript
[04:09]2018年度DOTA2社区贡献奖-完美盛典
2018/12/16 DOTA
Python开发常用的一些开源Package分享
2015/02/14 Python
python3爬取淘宝信息代码分析
2018/02/10 Python
Python中循环后使用list.append()数据被覆盖问题的解决
2018/07/01 Python
matplotlib调整子图间距,调整整体空白的方法
2018/08/03 Python
pandas DataFrame 删除重复的行的实现方法
2019/01/29 Python
python实现海螺图片的方法示例
2019/05/12 Python
Python JSON常用编解码方法代码实例
2020/09/05 Python
HTML5中实现拖放效果无须借助javascript
2012/12/26 HTML / CSS
Footshop罗马尼亚:最好的运动鞋选择
2019/09/10 全球购物
密封类可以有虚函数吗
2014/08/11 面试题
幼儿园毕业家长感言
2014/02/10 职场文书
人力资源经理的岗位职责范本
2014/02/28 职场文书
大学新闻系求职信
2014/06/03 职场文书
党的群众路线教育实践活动批评与自我批评发言稿
2014/10/16 职场文书
廉政文化进校园广播稿
2014/10/20 职场文书
525心理健康活动总结
2015/05/08 职场文书
2016入党积极分子党课培训心得体会
2016/01/06 职场文书
2016年社区六一儿童节活动总结
2016/04/06 职场文书
在JavaScript中如何使用宏详解
2021/05/06 Javascript
超详细Python解释器新手安装教程
2021/05/10 Python