1. 面向对象编程基础

把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。

简而言之,面向对象在我看来,把一个实体的属性抽象出来,然后去操作这个抽象的实体,这个实体可以有种种行为(方法),而不在是简单的单一结果。

面向对象编程的2个非常重要的概念:类和对象

对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念——类

类就相当于制造飞机时的图纸,用它来进行创建的飞机就相当于对象

类和对象之间的关系

 

面向对象有三大支柱:封装、继承和多态。

 

2. 定义类和创建对象

定义类:在Python中可以使用class关键字定义类,然后在类中通过之前学习过的函数来定义方法

定义一个类

class Car:
# 方法
def getCarInfo(self):
print('车轮子个数:%d, 颜色%s'%(self.wheelNum, self.color)) def move(self):
print("车正在移动...")

  

创建一个对象

# -*- coding:utf-8 -*-
"""
定义一个类,再创建一个对象
version:0.1
author:coke
"""
#类
class Car:
#方法
def getCarInfo(self):
print('车轮子个数:%d,颜色%s'%(self.wheelNum,self.color)) def move(self):
print("车正在移动") BMW = Car()
BMW.color = "黑色"
BMW.wheelNum = 4
BMW.getCarInfo()
BMW.move()

注:这里出现了 self,所谓的self,可以理解为自己 ,某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

 

3. init() 方法

在上一小节的demo中,我们已经给BMW这个对象添加了2个属性,wheelNum(车的轮胎数量)以及color(车的颜色),试想如果再次创建一个对象的话,肯定也需要进行添加属性,显然这样做很费事,那么有没有办法能够在创建对象的时候,就顺便把车这个对象的属性给设置呢?

# -*- coding:utf-8 -*-
"""
_init_使用
version:0.1
author:coke
"""
#定义汽车类
class Car:
def __init__(self):
self.wheelNum = 4
self.color = '蓝色'
def move(self):
print('车在跑,目标:夏威夷') # 创建对象
BMW = Car()
print('车的颜色为:%s'%BMW.color)
print('车轮胎数量为:%d'%BMW.wheelNum)

 

总结:当创建Car对象后,在没有调用__init__()方法的前提下,BMW就默认拥有了2个属性wheelNum和color,原因是__init__()方法是在创建对象后,就立刻被默认调用了

 

4. 魔法方法

在python中方法名如果是__xxxx__()的,那么就有特殊的功能,因此叫做“魔法”方法

当使用print输出对象的时候,只要自己定义了__str__(self)方法,那么就会打印从在这个方法中return的数据

# -*- coding:utf-8 -*-
"""
_init_使用
version:0.1
author:coke
"""
#定义汽车类
class Car:
def __init__(self,newWheelNum,newColor):
self.wheelNum = newWheelNum
self.color = newColor
def __str__(self):
msg = "车轮胎数:" + str(self.wheelNum) + " 车的颜色:" + self.color
return msg def move(self):
print("车在跑,目标夏威夷") BWM = Car(4,"green")
BWM.move()
print(BWM)

 

5. 访问可见性问题

在很多面向对象编程语言中,我们通常会将对象的属性设置为私有的(private)或受保护的(protected),简单的说就是不允许外界访问,而对象的方法通常都是公开的(public),因为公开的方法就是对象能够接受的消息。在Python中,属性和方法的访问权限只有两种,也就是公开的和私有的,如果希望属性是私有的,在给属性命名时可以用两个下划线作为开头,下面的代码可以验证这一点。

# -*- coding:utf-8 -*-
"""
测试可见性
version:0.1
author:coke
"""
class Test:
def __init__(self, foo):
self.__foo = foo def __bar(self):
print(self.__foo)
print('__bar') def main():
test = Test('hello')
# AttributeError: 'Test' object has no attribute '__bar'
test.__bar()
# AttributeError: 'Test' object has no attribute '__foo'
print(test.__foo) if __name__ == "__main__":
main()

 

但是,Python并没有从语法上严格保证私有属性或方法的私密性,它只是给私有的属性和方法换了一个名字来“妨碍”对它们的访问,事实上如果你知道更换名字的规则仍然可以访问到它们,下面的代码就可以验证这一点。之所以这样设定,可以用这样一句名言加以解释,就是“We are all consenting adults here”。因为绝大多数程序员都认为开放比封闭要好,而且程序员要自己为自己的行为负责。

# -*- coding:utf-8 -*-
"""
测试可见性
version:0.2
author:coke
"""
class Test:
def __init__(self,foo):
self.__foo = foo
def __bar(self):
print(self.__foo);
print("__bar") def __str__(self):
return self.__foo
def main():
test = Test("hello")
print(test)
#事实上还是可以在外部访问 __foo属性
print(test._Test__foo) if __name__ == "__main__":
main()

在实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问(后面会讲到)。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重

 

5. 练习

为了更好的理解面向对象编程,下面以“烤地瓜”为案例,进行分析

示例属性如下:

  • cookedLevel : 这是数字;0~3表示还是生的,超过3表示半生不熟,超过5表示已经烤好了,超过8表示已经烤成木炭了!我们的地瓜开始时时生的
  • cookedString : 这是字符串;描述地瓜的生熟程度
  • condiments : 这是地瓜的配料列表,比如番茄酱、芥末酱等

示例方法如下:

  • cook() : 把地瓜烤一段时间
  • addCondiments() : 给地瓜添加配料
  • __init__() : 设置默认的属性
  • __str__() : 让print的结果看起来更好一些

 

1、定义类,并且定义__init__()方法

#定义`地瓜`类
class SweetPotato:
'这是烤地瓜的类' #定义初始化方法
def __init__(self):
self.cookedLevel = 0
self.cookedString = "生的"
self.condiments = []

 

2、添加"烤地瓜"方法

#烤地瓜方法
def cook(self, time):
self.cookedLevel += time
if self.cookedLevel > 8:
self.cookedString = "烤成灰了"
elif self.cookedLevel > 5:
self.cookedString = "烤好了"
elif self.cookedLevel > 3:
self.cookedString = "半生不熟"
else:
self.cookedString = "生的"

 

3、基本的功能已经有了一部分,赶紧测试一下

mySweetPotato = SweetPotato()
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)

 

4、定义addCondiments()方法和__str__()方法

    def __str__(self):
msg = self.cookedString + " 地瓜"
if len(self.condiments) > 0:
msg = msg + "("
for temp in self.condiments:
msg = msg + temp + ", "
msg = msg.strip(", ") msg = msg + ")"
return msg def addCondiments(self, condiments):
self.condiments.append(condiments)

 

全部代码

# -*- coding:utf-8 -*-
"""
烤地瓜
"""
class SweetPotato:
"这是烤地瓜的类" #定义初始化方法
def __init__(self):
self.cookedLevel = 0
self.cookedString = "生的"
self.condiments = [] #添加烤地瓜的方法
def cook(self,time):
self.cookedLevel += time
if self.cookedLevel > 10:
self.cookedString = "烤成灰了"
elif self.cookedLevel > 5:
self.cookedString = "烤好了"
elif self.cookedLevel > 3:
self.cookedString = "半生不熟"
else:
self.cookedString = "生的" #添加配料
def addCondiments(self,condiment):
self.condiments.append(condiment) def __str__(self):
msg = self.cookedString + "地瓜"
if len(self.condiments) > 0:
msg = msg + "("
for temp in self.condiments:
msg = msg + temp + ", "
msg = msg.strip(", ")
msg = msg + ")"
return msg mySweetPotato = SweetPotato()
print("------有了一个地瓜,还没有烤--------")
print(mySweetPotato.cookedLevel)
print(mySweetPotato.cookedString)
print(mySweetPotato.condiments)
print("---------接下来进行烤地瓜------------")
print("---------地瓜烤了四分钟------------")
mySweetPotato.cook(4)
print(mySweetPotato)
print("---------地瓜又烤了分钟-----------")
mySweetPotato.cook(3)
print(mySweetPotato)
print("----------添加配料番茄酱------------")
mySweetPotato.addCondiments("番茄酱")
mySweetPotato.addCondiments("芥末酱")
mySweetPotato.cook(2)
print(mySweetPotato)

输出结果

Python基础 — 面向对象编程基础的更多相关文章

  1. 大数据技术之_16_Scala学习_04_函数式编程-基础+面向对象编程-基础

    第五章 函数式编程-基础5.1 函数式编程内容说明5.1.1 函数式编程内容5.1.2 函数式编程授课顺序5.2 函数式编程介绍5.2.1 几个概念的说明5.2.2 方法.函数.函数式编程和面向对象编 ...

  2. Python——11面向对象编程基础

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...

  3. Python进阶(面向对象编程基础)(三)

    6.类属性和实例属性名字冲突怎么办 修改类属性会导致所有实例访问到的类属性全部都受影响,但是,如果在实例变量上修改类属性会发生什么问题呢? class Person(object): address ...

  4. Python进阶(面向对象编程基础)(二)

    1.初始化实例属性 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ = 'ziv·chan' #定义Person类的__init__方法 ...

  5. Python进阶(面向对象编程基础)(一)

    鉴于昨天被类和函数折腾得晕头转向,今特把类的知识翻出来温习. 1.定义类并创建实力对象 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ ...

  6. Python进阶(面向对象编程基础)(四)

    1.方法也是属性 我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象: class Person(object): def __init__(self, name, score) ...

  7. python基础——面向对象编程

    python基础——面向对象编程 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...

  8. Python 面向对象编程基础

    Python 面向对象编程基础 虽然Pthon是解释性语言,但是Pthon可以进行面向对象开发,小到 脚本程序,大到3D游戏,Python都可以做到. 一类: 语法: class 类名: 类属性,方法 ...

  9. Python学习-第三天-面向对象编程基础

    Python学习-第三天-面向对象编程基础 类和对象 简单的说,类是对象的蓝图和模板,而对象是类的实例.这个解释虽然有点像用概念在解释概念,但是从这句话我们至少可以看出,类是抽象的概念,而对象是具体的 ...

随机推荐

  1. 纯C语言实现顺序队列

    #include <stdio.h> #include <stdlib.h> #define MAXSIZE 6 typedef int QElemType; typedef ...

  2. MySQL基础(三)(操作数据表中的记录)

    1.插入记录INSERT 命令:,expr:表达式 注意:如果给主键(自动编号的字段)赋值的话,可以赋值‘NULL’或‘DEFAULT’,主键的值仍会遵守默认的规则:如果省略列名的话,所有的字段必须一 ...

  3. 跨域问题 Blocked a frame with origin "http://......" from accessing a cross-origin frame.

    为了轻松偷懒,不想从目的项目中开发目标项目中的页面,但目的项目中需要获取老项目中的页面,这里用了iframe跨域链接页面出现了问题 Blocked a frame with origin " ...

  4. 深入理解Vue组件3大核心概念

    摘要: 搞懂Vue组件! 作者:浪里行舟 原文:详解vue组件三大核心概念 Fundebug经授权转载,版权归原作者所有. 前言 本文主要介绍属性.事件和插槽这三个vue基础概念.使用方法及其容易被忽 ...

  5. Java常用算法总结

    冒泡排序 从左到右不断交换相邻逆序的元素,在一轮的循环之后,可以让未排序的最大元素上浮到右侧. 在一轮循环中,如果没有发生交换,那么说明数组已经是有序的,此时可以直接退出. 代码如下: public ...

  6. nginx+tomcat集群时,tomcat参数优化

    maxKeepAliveRequests=“1”: nginx动态的转给tomcat,nginx是不能keepalive的,而tomcat端默认开启了keepalive,会等待keepalive的ti ...

  7. SpringBoot的学习一:入门篇

    SpringBoot是什么: SpringBoot是Spring项目中的一个子工程,是一个轻量级框架. SpringBoot框架中有两个个非常重要的策略:开箱即用和约定优于配置 一.构建工程 1.开发 ...

  8. 002-Zabbix 前端配置

    Zabbix 前端配置 [基于此文章的环境]点我快速打开文章 [官方地址]点我快速打开文章 第 1 步 在浏览器中,打开 Zabbix URL:http:// <server_ip_or_nam ...

  9. Codeforces Round #304 (Div. 2)(CF546D) Soldier and Number Game(线性筛)

    题意 给你a,b(1<=b<=a<=5000000)表示a!/b!表示的数,你每次可以对这个数除以x(x>1且x为这个数的因子)使他变成a!/b!/x, 问你最多可以操作多少次 ...

  10. FCOS及其和Faster R-CNN的区别

    RetinaNet,SSD,YOLOv3,Faster R-CNN等都是Anchor-based的检测器,即需要预定义的Anchor boxes来进行训练.FCOS是一种Anchor-free和Pro ...