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 相关文章推荐
shelve  用来持久化任意的Python对象实例代码
Oct 12 Python
python基础教程之匿名函数lambda
Jan 17 Python
Python实现Linux中的du命令
Jun 12 Python
老生常谈Python startswith()函数与endswith函数
Sep 08 Python
python实现用户管理系统
Jan 10 Python
浅谈Django中的数据库模型类-models.py(一对一的关系)
May 30 Python
Python静态类型检查新工具之pyright 使用指南
Apr 26 Python
flask应用部署到服务器的方法
Jul 12 Python
使用python实现对元素的长截图功能
Nov 14 Python
关于python的缩进规则的知识点详解
Jun 22 Python
Python根据指定文件生成XML的方法
Jun 29 Python
Python机器学习应用之工业蒸汽数据分析篇详解
Jan 18 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
自己动手做一个SQL解释器
2006/10/09 PHP
php结合正则批量抓取网页中邮箱地址
2015/05/19 PHP
PHP session垃圾回收机制实例分析
2019/06/28 PHP
PHP实现提高SESSION响应速度的几种方法详解
2019/08/09 PHP
一个关于jqGrid使用的小例子(行按钮)
2011/11/04 Javascript
固定网页背景图同时保持图片比例的思路代码
2013/08/15 Javascript
js控制浏览器全屏示例代码
2014/02/20 Javascript
JavaScript将字符串转换为整数的方法
2015/04/14 Javascript
jquery自定义插件——window的实现【示例代码】
2016/05/06 Javascript
AngularJs Scope详解及示例代码
2016/09/01 Javascript
Javascript 调用 ActionScript 的简单方法
2016/09/22 Javascript
vue过渡和animate.css结合使用详解
2017/06/14 Javascript
js禁止Backspace键使浏览器后退的实现方法
2017/09/01 Javascript
JavaScript解决浮点数计算不准确问题的方法分析
2018/07/09 Javascript
webpack4.x CommonJS模块化浅析
2018/11/09 Javascript
vue之封装多个组件调用同一接口的案例
2020/08/11 Javascript
JavaScript canvas实现雨滴特效
2021/01/10 Javascript
利用python循环创建多个文件的方法
2018/10/25 Python
django Admin文档生成器使用详解
2019/07/22 Python
Pytorch抽取网络层的Feature Map(Vgg)实例
2019/08/20 Python
Python socket模块ftp传输文件过程解析
2019/11/05 Python
python Canny边缘检测算法的实现
2020/04/24 Python
Css3新特性应用之视觉效果实例
2016/12/12 HTML / CSS
css3 flex实现div内容水平垂直居中的几种方法
2020/03/27 HTML / CSS
欧洲最大的预定车位市场:JustPark
2020/01/06 全球购物
伊莱克斯阿根廷网上商店:Tienda Electrolux
2021/03/08 全球购物
路德维希•贝克(LUDWIG BECK)中文官网:德国大型美妆百货
2020/09/19 全球购物
写演讲稿要注意的六件事
2014/01/14 职场文书
小松树教学反思
2014/02/11 职场文书
贯彻落实“八项规定”思想汇报
2014/09/13 职场文书
重阳节慰问信
2015/02/15 职场文书
2015年超市工作总结
2015/04/09 职场文书
2016优秀护士求职自荐信
2016/01/28 职场文书
优胜劣汰,强者为王——读《鲁滨逊漂流记》有感
2019/08/15 职场文书
React中的Context应用场景分析
2021/06/11 Javascript
Python echarts实现数据可视化实例详解
2022/03/03 Python