背景介绍:
Python 支持三种形式的编程,分别是:“命令式”、“函数式”和“面向对象式”。
很多优秀的开源 Python 项目里都用到了“面向对象式”编程,本文 Sugar 就来说一说用 Python 做面向对象编程所必需的基础知识。

我们之前已经看过两种编程范例:命令式(使用语句,循环和函数作为子例程)和函数(使用纯函数,高阶函数和递归)。
另一个非常流行的范例是面向对象编程(OOP)。

使用创建对象,这实际上是 OOP 的焦点。
类描述对象是什么,就像是对象的蓝图、描述或定义。
可以使用相同的类来创建多个不同的对象。

使用关键字 class缩进来写类,例如:

class Cat:  def __init__ (self, color, legs):    self.color = color    self.legs  = legsfelix = Cat("ginger", 4)rover = Cat("dog-coloured", 4)stumpy = Cat("brown", 3)

这个代码定义了一个名为 Cat 的类,它有两个属性:colorlegs
然后,使用这个类创建了 3 个单独的对象。

__init__

__init__ 方法是类里最重要的方法。
当用一个类名像使用函数一样创建对象时会调用这个函数。

类内所有的方法的第一个参数都必须是self(尽管并未明确传递),Python 会将 self 参数添加到列表中;调用方法时不需要包含它。在方法定义中,self 指的是调用该方法的对象实例。

类的实例具有属性,这些属性是与它们相关联的数据。
在上面的示例中,Cat 实例具有属性“颜色”和“腿”。可以通过在实例后面放置一个和属性名来访问它们。因此,在 __init__  方法中,self.attribute创建和设置实例属性,并用于给属生赋初始值
例:

class Cat:  def __init__(self, color, legs):    self.color = color    self.legs  = legsfelix = Cat("ginger", 4)print(felix.color)

输出:

>>>ginger>>>

在上面的例子中,__init__方法接受两个参数并将它们分配给对象属性。该 __init__ 方法被称为类的构造函数

【填空题】在空白处填入关键字来创建一个类和这个类的构造函数,构造函数有一个形式参数,并且用这个形式参数给“name”属性赋值,最后用这个类创建一个对象。

______ Student:  def ______(self, name);    self______ = nametest = Student("Bob"_

【答案】class , __init__ , .name , )

方法

可以通过自定义方法来给类加入功能。
记住:所有的方法必须self作为第一个形参。
跟访问属性的语法一样,类的对象依然用方式使用自定义方法。
例:

class Dog:  def __init__(self, name, color):    self.name = name    self.color = color  def bark(self):    print("Woof!")fido = Dog("Fido", "brown")print(fido.name)fido.bark()

输出:

>>>FidoWoof!>>>

可以在类体内分配变量作为类的属性,类内分配的变量可以通过类的对象访问,也可以直接用类名访问
例:

class Dog:  legs = 4  def __init__(self, name, color):    self.name = name    self.color = colorfido = Dog("Fido", "brown")print(fido.legs)print(Dog.legs)

输出:

>>>44>>>

类内分配的变量被类的所有对象所共享。

【填空题】创建一个类并在类内创建一个 sayHi() 方法。

class Student_  def __init__(self, name):    self.name = name    ______sayHi(______):    print("Hi from "+ _____.name)s1 = Student("Amy")s1.sayHi()

【答案】: , def , self , self

继承

继承为类之间共享功能提供了一个途径。
试想一下有下面几个类:猫、狗和兔子等。尽管它们有不同点(比如狗类定义了“汪汪”方法),仍然可以找到它们之间共同的地方(比如都有颜色和名字)。
这些共同点可以让它们都继承于“动物”类来实现。
让一个类继承于另一个类的方法是:在子类定义时加个括号并把父类放在括号里。
例:

class Animal:   def __init__(self, name, color):    self.name = name    self.color = colorclass Cat(Animal):  def purr(self):    print("Purr...")class Dog(Animal):  def bark(self):    print("Woof!")fido = Dog("Fido", "brown")print(fido.color)fido.bark()

输出:

>>>brownWoof!>>>

下面哪个选项正确的定义了继承于 Egg 类的 Spam 类

  • [ ] class Egg(Spam):

  • [ ] class (Spam)Egg:

  • [x] class Spam(Egg):

多态

从别的类继承来的类叫做子类
被子类继承的类叫做“父类”。
当子类内有与父类相同的属性或方法时,相同的部分被覆写。
例:

class Wolf:   def __init__(self, name, color):    self.name = name    self.color = color  def bark(self):    print("Grr...")class Dog(Wolf):  def bark(self):    print("Woof")husky = Dog("Max", "grey")husky.bark()

输出:

>>>Woof>>>

在这个例子里,Wolf 是父类,Dog 是子类。

【问】下面代码的输出结果是什么?

class A:  def method(self):    print(1)class B(A):  def method(self):    print(2)B().method()

【答】2

继承可传递

继承可以是间接的。一个类可以继承于另一个类,而另一个类可以是第三个类的子类。
例:

class A:  def method(self):    print("A method")class B(A):  def another_method(self):    print("B method")class C(B):  def third_method(self):    print("C method")c = C()c.method()c.another_method()c.third_method()

输出:

>>>A methodB methodC method>>>

注意:不能环形继承。

【问】下面的程序输出什么?

class A:  def a(self):    print(1)class B(A):  def a(self):    print(2)class C(B):  def c(self):    print(3)c = C()c.a()

【答】 2

子类内调用父类函数

super() 函数的使用。
例:

class A:  def spam(self):    print(1)class B(A):  def spam(self):    print(2)    super().spam()B().spam()

输出:

>>>21    >>>

super().spam() 调用了父类的 spam() 函数。

魔法方法

魔法方法的命名由两个下划线开头和两个下划线结尾,是特殊的方法。
目前为止我们接触过唯一的一个魔法方法是 init,但除此之外还有别外的一些魔法方法。
这些魔法方法用于创建不能由普通方法表示的特殊方法。

一、运算符重载

运算符重载是魔法方法使用的普遍例子。
运算符重载的目的是让类的对象能够使用 + 、 这样的符号进行相应的操作。
下面的例子里的魔法方法是 *add

例:

class Vector2D:  def __init__(self, x, y):    self.x = x    self.y = y  def __add__(self, other):    return Vector2D(self.x + other.x, self.y + other.y)first = Vector2D(5, 7)second = Vector2D(3, 9)result = first + secondprint(result.x)print(result.y)

输出:

>>>816    >>>

上面的例子返回了一个新的对象并将之赋给了 result。

常用的运算符重载如下表:

函数名 运算
__sub__ -
__mul__ *
__truediv__ /
__floordiv__ //
__mod__ %
__pow__ **
__and__ &
__xor__ ^
__or__ \

通常情况下表达式 x + y 译成 x.__add__(y)
然而,如果 x 尚未实现 __add__,并且 x 和 y 是不同类型的,那么将译成y.__radd__(x)。上面表格里的所有方法都有相应的 r 方法。
例:

class SpecialString:  def __init__(self, cont):    self.cont = cont  def __truediv__(self, other):    line = "=" * len(other.cont)    return "\n".join([self.cont, line, other.cont])spam = SpecialString("spam")hello = SpecialString("Hello world!")print(spam / hello)

输出:

>>>spam============Hello world!>>>

【问】如果没有定义任何魔法方法,那么 A()^B() 将会被译成什么样子?

  • [ ] A().__xor__(B())

  • [x] B().__rxor__(A())

  • [ ] B().xor(A())

二、比较运算符

函数名 比较运算
__lt__ <
__le__ <=
__eq__ ==
__ne__ !=
__gt__ >
__ge__ >=

如果没有定义 __ne__,则返回 __eq__ 的取反。
例:

class SpecialString:  def __init__(self, cont):    self.cont = cont  def __gt__(self, other):    for index in range(len(other.cont)+1):      result = other.cont[:index] + ">" + self.cont      result += ">" + other.cont[index:]      print(result)spam = SpecialString("spam")eggs = SpecialString("eggs")spam > eggs

输出:

>>>>spam>eggse>spam>ggseg>spam>gsegg>spam>seggs>spam>>>>

三、容器相关魔法方法

有几种能使类像容器一样使用的魔法方法。__len__ 相当于 len()__getitem__ 用来获取索引位置的值__setitem__ 用来分配索引位置的值__delitem__ 用来删除索引位置的值__iter__  用来迭代对象(比如在循环中使用)__contains__ 相当于 in

还有很多其余的魔法方法这里没有提及,比如 __call__ 用来像函数一样调用对象,另外还有 __int____str__ 等用于将对象转换为内置类型。
例:

import randomclass VagueList:  def __init__(self, cont):    self.cont = cont  def __getitem__(self, index):    return self.cont[index + random.randint(-1, 1)]  def __len__(self):    return random.randint(0, len(self.cont)*2)vague_list = VagueList(["A", "B", "C", "D", "E"])print(len(vague_list))print(len(vague_list))print(vague_list[2])print(vague_list[2])

输出:(因为有 random 参与,所以输出不唯一)

>>>67DC>>>

【问】x[y]=z 译成什么样子?

  • [ ] y.__getitem__(x,z)

  • [ ] x.setitem(z,y)

  • [x] x.__setitem__(y,z)

对象生命周期

对象的生成周期由:创建操作销毁三个部分组成。

对象生命周期的第一阶段是对象所属类的定义

下一阶段是当调用 __init__ 时进行的实例化,此时会分配内存给对像实例。在此之前会调用类的 __new__ 方法。通常只有在特殊情况下才将其覆盖。

经历过以上过程后,对象就可以被使用了。

在对象建立后,可以通代码在对象上调用函数以及访问对象的属性与对象进行交互。

最后,在对象结束使用的时候就可以把对象销毁。

对象的销毁

当对象被销毁后,给该对象分配的内存就随之被释放,之后被释放的内存可以用于做其他的事情。

对象的销毁发生在对象的引用计数归零时。引用计数是指与对象相关的变量或其他元素正在被使用的数量。如果没有使用中的元素(即引用数为零)就表示该对象与程序运行无关,所以这个对象就可以被安全地销毁。

在某些特殊的情况下,两个甚至更多对象只能相互引用,因此也能够被删除。

del 用于删除对象。del的魔法方法是 __del__

当对象不再被使用时,对象的删除过程称为“垃圾收集”。总的来说,对象的引用计数增加发生在被分配了新的名字、放入了一个容器(列表、元组、词典)的时候。对象引用计数的减少发生在使用 del 删除对象、对象被重新分配、对象引用超出范围的情况下。当对象的引用计数归零时,Python 会自动地销毁它。例如:

a = 42 # 创建对象b = a # 引用计数增加c = [a] # 引用计数增加del a # 引用计数减少b = 100 # 引用计数减少c[0] = -1 # 引用计数减少

数据隐藏

面向对象编程的一个重要部分是封装,就是把相关的变量和函数打包在一个类的实例(对象)当中以便使用。这就应当隐藏类的实现细节,把干净标准的接口提供给想要使用该类的用户。

在其他的编程语言中通常用 private 私有成员来完成数据隐藏,私有成员可以阻止外部访问类中的方法和属性。

Python 的哲学略有不同。Python 并不严格阻止对类内任何部分的访问,也就是说无法强制方法或属性完全对外隐藏。

弱私有方法和属性

在 Python 中私有的方法或属性以单个下划线开头,表示它们是私有的,不应该由外部访问。但“不应该”、“不提倡”并不表示“不能”。唯一的影响是:这些以单个下划线开头的方法或属性不能通过 from module_name import * 的方式导入。

class Queue:  def __init__(self, contents):    self._hiddenlist = list(contents)  def push(self, value):    self._hiddenlist.insert(0, value)     def pop(self):    return self._hiddenlist.pop(-1)  def __repr__(self):    return "Queue({})".format(self._hiddenlist)queue = Queue([1, 2, 3])print(queue)queue.push(0)print(queue)queue.pop()print(queue)print(queue._hiddenlist)

输出:

>>>Queue([1, 2, 3])Queue([0, 1, 2, 3])Queue([0, 1, 2])[0, 1, 2]>>>

强私有方法和属性

在 Python 中私有的方法或属性以双下划线开头,强私有方法或属性无法从类外直接访问。这样做的目的并不是为了完全的数据隐藏,而是为了防止子类中有同名的方法或者属性。

_类名是用类外访问强私有方法和属性的间接办法,例如:

class Spam:  __egg = 7  def print_egg(self):    print(self.__egg)s = Spam()s.print_egg()print(s._Spam__egg)print(s.__egg)

输出:

>>>77AttributeError: 'Spam' object has no attribute '__egg'>>>

问:如何从 b 类外访问 __a
答:_b__a

类方法

类方法用类名调用,传给类的 cls 参数(对比理解:常规方法传给 self 参数)。类方法用 @classmethod标记,如下:

class Rectangle:  def __init__(self, width, height):    self.width = width    self.height = height  def calculate_area(self):    return self.width * self.height  @classmethod  def new_square(cls, side_length):    return cls(side_length, side_length)square = Rectangle.new_square(5)print(square.calculate_area())

输出:

>>>25>>>

静态方法

静态方法与普通方法的差别是:不接受其他参数(指self参数)。静态方法用@staticmethod标记,如下:

class Pizza:  def __init__(self, toppings):    self.toppings = toppings  @staticmethod  def validate_topping(topping):    if topping == "pineapple":      raise ValueError("No pineapples!")    else:      return Trueingredients = ["cheese", "onions", "spam"]if all(Pizza.validate_topping(i) for i in ingredients):  pizza = Pizza(ingredients) 

当 ingredients 里有 pineapple 时就抛出异常。

注意:上例中的 i 有点先使用后定义的感觉。对于 Sugar 习惯了 C/C++ 的人来讲一开始觉得很不适应,但确定这就是常人的表达习惯。Sugar 觉得“严谨”是后天训练的,而并不是所有人都乐于后天“严谨”的训练,这是为什么 Python 会更广泛地被接受的原因之一吧。

只读属性

通过 @property 给方法加只读属性,如下:

class Pizza:  def __init__(self, toppings):    self.toppings = toppings      @property  def pineapple_allowed(self):    return Falsepizza = Pizza(["cheese", "tomato"])print(pizza.pineapple_allowed)pizza.pineapple_allowed = True

输出:

>>>FalseAttributeError: can't set attribute>>>

setter 与 getter

看下面代码了解 setter 的作用,getter 类似。当有具体需求的使候能想到就可以了,不做多余的说明。

注意:pineapple_allowed()方法的多态:

class Pizza:  def __init__(self, toppings):    self.toppings = toppings    self._pineapple_allowed = False  @property  def pineapple_allowed(self):    return self._pineapple_allowed  @pineapple_allowed.setter  def pineapple_allowed(self, value):    if value:      password = input("Enter the password: ")      if password == "Sw0rdf1sh!":        self._pineapple_allowed = value      else:        raise ValueError("Alert! Intruder!")pizza = Pizza(["cheese", "tomato"])print(pizza.pineapple_allowed)pizza.pineapple_allowed = Trueprint(pizza.pineapple_allowed)

运行结果:

>>> FalseEnter the password: Sw0rdf1sh!True>>> 

PS

一、基本概念
01、Python 是什么
02、第一个 Python 程序
03、计算
04、浮点数
05、幂、商、余
06、字符串
07、简单输入输出
08、字符串操作
09、类型转换
10、变量
11、就地操作
二、控制结构
01、布尔值与比较
02、if 语句
03、else 语句
04、布尔逻辑
05、运算符优先级
06、while 循环
07、列表
08、列表操作
09、列表功能函数
10、range 函数
11、for 循环
三、函数与模块
01、代码重用
02、函数
03、函数参数
04、函数返回值
05、注释
06、函数的特别用法
四、异常
01、异常
02、异常处理
03、finally
04、抛出异常
05、断言
五、文件
01、打开文件
02、读文件
03、写文件
04、文件操作的好习惯

应用篇
01、MicroPython 实时体温获取

关注作者

欢迎扫码关注我的公众号MultiMCU EDU

提示:在公众号“关于我”页面可加作者微信好友。

喜欢本文求点赞,有打赏我会更有动力。

python用类名直接调用方法_一文读全 Python 的面向对象编程方法相关推荐

  1. python输入什么就输出什么_一文读懂Python的输入和输出

    本文介绍了Python的输入和输出,既然是Python代码,那么就一定有输出量,那么,Python是如何输出的呢? 输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'h ...

  2. python读取枚举_一文读懂Python 枚举

    enum是一组绑定到唯一常数值的符号名称,并且具备可迭代性和可比较性的特性.我们可以使用 enum 创建具有良好定义的标识符,而不是直接使用魔法字符串或整数,也便于开发工程师的代码维护. 创建枚举 我 ...

  3. python源代码最多的学习网站_史上最全Python学习资料大合集分享

    Python有多火就不用说了,之前也零散地分享过一些Python学习开发资料. 本次将分享Python学习资料合集.合集哦,你品,你细品! 在分享之前,还是要啰嗦一下,不然文章字数太少,不太好看. P ...

  4. python输入什么就输出什么意思_一文读懂Python的输入和输出

    本文介绍了Python的输入和输出,既然是Python代码,那么就一定有输出量,那么,Python是如何输出的呢? 输出 用print()在括号中加上字符串,就可以向屏幕上输出指定的文字.比如输出'h ...

  5. 廖雪峰讲python高阶函数求导公式_一文读懂Python 高阶函数

    高阶函数 将函数作为参数传入,这样的函数称为高阶函数.函数式编程就是指这种高度抽象的编程范式. 变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函 ...

  6. python中有哪些重要的书写规则_一文读懂Python代码的书写规范

    Python代码的书写规范 1. 一致性的建议 打破一条既定规则的两个好理由 当应用这个规则将导致代码可读性下降,即使对于某人来说他已经习惯于按照这条规则来阅读代码了 为了和周围的代码保持一致而打破规 ...

  7. 读懂python语言_一文读懂python反射机制

    反射 反射机制就是在运行时,动态的确定对象的类型,并可以通过字符串调用对象属性.方法.导入模块,是一种基于字符串的事件驱动.解释型语言:程序不需要编译,程序在运行时才翻译成机器语言,每执行一次都要翻译 ...

  8. python中row是什么意思_一文搞懂Python中的yield

    关注公众号「Python七号」,及时 get Python 技能. yield 可以实现生成器,可以实现协程. 什么是生成器,什么是协程,如果还不了解,可以继续往下看,概念可以不懂,只要理解它的作用和 ...

  9. networkx edge 属性_一文读懂Python复杂网络分析库networkx | CSDN博文精选

    作者 | yyl424525 来源 | CSDN博客 文章目录 1. 简介 安装 支持四种图 绘制网络图基本流程 2. Graph-无向图 节点 边 属性 有向图和无向图互转 3. DiGraph-有 ...

最新文章

  1. Bootstrap 模态框上下居中
  2. im4java转换图片格式_ImageMagick和im4java处理图片[转]
  3. 每日一皮:没想到现实比赛里也能和拳皇一样蓄力攻击...
  4. 【2021年度训练联盟热身训练赛第二场】Binarize It(python)
  5. 《Python编程快速上手——让繁琐工作自动化》——第一部分 Python编程基础 第1章 Python基础 1.1 在交互式环境中输入表达式...
  6. Python编程4道练习题
  7. Cloud for Customer根据后台数据实时刷新的逻辑调试
  8. html5贝塞尔,使用HTML5画布绘制贝塞尔曲线
  9. python程序写诗_python写的简单发送邮件的脚本
  10. 【HDU - 1031 】Design T-Shirt(水题 排序)
  11. 幽幽的灵光射不出你想要的疯狂
  12. 数据结构 3-2-2 队列的顺序存储实现
  13. Log4net日志记录包
  14. Android 自定义ScrollView 支持惯性滑动,惯性回弹效果。支持上拉加载更多
  15. MHEG5简介amp;多媒体技术教程
  16. 1- mongoDB安装及基础
  17. Caused by: org.apache.thrift.TApplicationException: Required field ‘filesAdded‘ is unset
  18. Sql Server 时间格式转换
  19. obv代码matlab,obv指标源代码,标准obv指标源代码
  20. python实现数据可视化软件_基于Python实现交互式数据可视化的工具

热门文章

  1. 关于Rigidbody,Collider和CharacterController三者之间的关系和用法的总结
  2. CSS样式属性margin,padding详解
  3. 盖塔机器人好_盖塔机器人的十大谜团
  4. Python中的三目运算符(三元表达式)
  5. Codeforces 940E Cashback
  6. 37互娱,2019秋招提前批,Java服务端一面
  7. python中slice是什么类型,python中slice是什么类型_在python中,slice是一个副本还是一个poin...
  8. 基于 SpringBoot + MyBatis 的博客系统
  9. vue通过点击按钮弹出新窗口打开html文件
  10. python3各版本区别-Python各版本之间的区别