python03 面向对象的编程01
话不多说,直接进入正文:
- 写重复代码是非常不好的低级行为
- 你写的代码需要经常变更
while True: if cpu.usage > 90: mail(CPU报警) #(假设mail这里是一个发送邮件的功能,我们直接在括号内输入要发送的内容就行了) if mem.usage > 90: mail(内存报警) if disk.usage > 90: mail(磁盘报警)
但是随着知识的增长,此时我们学习了函数,了解到了函数式编程,那么可以把代码精简如下:
def judge_usage(name,content): #把判断功能和发送功能做成一个函数,直接传参就行了 if name > 90: mail(content) judge_usage(cpu.usage,cpu报警) #那么我们调用的时候直接传入内存,CPU,磁盘的使用率就行了。
好了到此为止我们觉得这个代码就行了,最起码把代码精简了,省去了重复的代码。
那么今天我们就来学习下 --> 面向对象的编程
#面对对象的编程 OOP class Role(object): #通过class这个关键字来创建一个类,Role表示这是类的名字,(object)是新式类的写法 必 须这么写(以后再说原因),表示继承object类,3.0以上的版本最好都写上。 def __init__(self,name,role,gun,life_value): #__init__用函数的话说这里就是Role类的初始化函数,使用类的专业名词就是说构造方法,在类 实例化的时候会默认执行。,这里的self表示为对象本身,而对象又是在实例化的时候创建的 self.name=name #把name赋值给self.name self.role=role self.gun=gun self.life_val=life_value def buy_gun(self,gun_name): #定义了一个buy_gun的方法 print("%s buy %s"%(self.name,gun_name)) self.gun=gun_name
我们这样使用这个类:
p1=Role('lisi','police','AK47',100) print('P1 ',p1.buy_gun('xxx')) #其实上面那语句 " p1=Role('lisi','police','AK47',100) " 等价于这句 Role(p1,'lisi','police','AK47',100),p1的所在的位置就对应的是self。这么做的目的就在于把'lisi','police','AK47',100和p1关联起来
说清楚点就是:实际上我们执行上面实例化的语句时做了两件事情
1 在内存开辟空间,指向p1这个变量名。
2 开始实例化了,调用了Role这个类,并且执行了__init__这个构造方法,相当于Role.__init__(p1,'lisi','police','AK47',100),注意看,p1占用了self的位置,为啥会这样,其实这么做的目的就在于把'lisi','police','AK47',100和刚才开辟的变量名p1关联起来,也许你就会问了,为啥要关联起来,如果不关联起来,那么这4个参数就没有跟谁了,解释器就会报错了。
3 所以说,p1=Role('lisi','police','AK47',100)这样一运行后,self.name = name ,self.role = role ...... 就把'lisi','police','AK47',100 这4个值放入了p1这个内存空间里面。
到此你也许会问为啥在第二个方法里面buy_gun还有个self呢?那么现在就解答你的问题。
虽然我们在实例化的时候把传入了那几个参数和p1关联起来了,但是我们在调用这个bug_gun方法的时候,需要告诉buy_gun,从谁那里获取信息,怎么去获取,于是把p1传给self,这样buy_gun才能够去访问p1的信息,所以能够打印出self.name(p1.name)来,其实最简单的回答就是调用方法的时候,这个方法得知道who are you。do you understand?? i think you will answer i do!!
好了,说了那么多,我们总结下出以下2点:
- 上面的这个p1=Role('lisi','police','AK47',100)动作,叫做类的“实例化”, 就是把一个虚拟的抽象的类,通过这个动作,变成了一个具体的对象了, 这个对象就叫做实例
- 刚才定义的这个类体现了面向对象的第一个基本特性,封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容
类的变量和实例的变量
class aa(object): x=0 def __init__(self,name): self.name=name def buy_some(self,goods_name): print("%s buying %s"%(self.name,goods_name)) bb=aa('bb') cc=aa('cc') aa.name='AK47' print('aa.weapon -->',aa.name) dd=aa('lisi') aa.x="AA's thing" aa.c='ccccccccc' aa.name='AA' bb.x='first' bb.c='xxxxxxx' bb.buy_some('lumia1020') print('bb.c-->',bb.c) #print('bb name--',bb.name) cc.buy_some('Nokia N1') print('cc c -->',cc.c)
从上面的代码中可以观察到1 在类里面的初始化方法__init__(),只有在调用的时候才才会创建self.name这个变量,倘若没有调用,那么直接运行aa.name是会报错的, 因为self.name是属于实例的变量(也叫成员属性,实例的属性),存在实例的内存中,不属于类的变量2 在类里面的变量x,在类没有被调用的也是存在的,存在类的内存里,所以aa.x是可以的3 aa这个类里面的buy_some方法,他是在aa这个类的内存里面的,不是在实例的内存里面的,所以实例每次调用这个buy_some方法的时候,都得 去类里面调用,并且告诉这个方法调用者的信息(其实就是实例的变量,buy_some第一个参数就是self,就是用来接受调用者信息的)。那会有人问了,为什么 不在每个实例化的过程中把buy_some方法都添加到实例内存中的,这样的话buy_some方法就在实例内存中,就不用在调用buy_some这个方法的告诉这个方法调 用者的信息,显然这个想法是错误的,为啥,因为函数对于外面是封闭的,所以调用buy_some的时候还得告诉调用者的信息,并且这样在每个实例中添加相同的 方法,那样只会占据更多的内存。那又有人会问了,我们可以把全局变量在buy_some这个方法中写死,如刚才实例化成的bb,cc,但是这里有个问题是,写死的 前提必须这个全局变量存在,但是没有实例化之前这个变量又是不存在的,所以这里是一个非常矛盾的问题。说了这么多就是想说明这点,类里面的方法除了构 造方法之外,都在类的内存里面,调用类里面的方法的时候必须告诉这个方法 调用者的信息
把上面3句话说精简点就是:
1 类的变量可以随时访问,实例的变量只有在实例化之后才能访问
2 类里面的方法除了构造方法之外,都在类的内存里面,调用类里面的方法的时候必须告诉这个方法 调用者的信息
3 倘若在类变量xx=None, 那么实例化之后,实例.xx='something'相当于把xx='something'放入了实例的内存里,如果直接实例.xx,就等于直接取类的变量。
类的继承
继承也是类的一大特性,它可以使用现有类的所有功能,并无需重新编写原来的类的情况下对这些功能进行扩展。
在这里我们要了解两个概念 :
-------------------------------------------
父类(也有人称超类,基类):被继承的类。
子类(也有人称派生类):通过继承创建的类。
-------------------------------------------
继承的过程,也就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Compostion)来实现。
继承是从一般到特殊的过程:父类是定义一般的方法,而子类是有特殊的方法,所以这就是从一般到继承的过程。
一般情况下一个子类只有一个基类,要实现多重继承,可以通过多级继承来实现。
我们看如下代码:
class animal(object): def __init__(self,name): self.name=name def eat(self): print("%s eating!!"%self.name) def drink(self): print("%s drink!!"%self.name) def sleep(self): print("%s sleep!!"%self.name) def discharge(self): print("%s discharge!!"%self.name) class people(animal): #这里开始继承animal类 def __init__(self,name,hair,thought): super(people,self).__init__(name) #super 是用来解决多重继承问题的,咱们后面会讲到 self.hair=hair self.thought=thought def whether_thought(self): print("He's name is %s ,and he can thought(%s) as people!!"%(self.name,self.thought)) class monkey(animal): def __init__(self,name,hair,climb): super(monkey,self).__init__(name) self.climb = climb def whether_climb(self): print("he is monkey and he's name is %s,he can climb(%s)"%(self.name,self.climb)) p1=people('ljf','black','yes') p1.whether_thought() #p1可以调用属于自己的方法,但是无法调用monkey的whether_climb的方法 print(p1.hair) p1.eat() #p1可以调用父类eat的方法 m1=monkey('wukong','yellow','can climb') m1.whether_climb() m1.drink() #m1可以调用父类的drink方法
python03 面向对象的编程01的更多相关文章
- JavaSE学习笔记05面向对象编程01
面向对象编程01 java的核心思想就是OOP 面向过程&面向对象 面向过程思想: 步骤清晰简单,第一步做什么,第二步做什么...... 面向过程适合处理一些较为简单的问题 面向对象思想: 物 ...
- PHP面向对象(OOP)编程入门教程
面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们就 ...
- 并发编程 01—— ThreadLocal
Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...
- 【PHP面向对象(OOP)编程入门教程】1.什么是面向对象?
面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程序是由单个能够起到子程序作用的单元或对象组合而成 ...
- 【PHP面向对象(OOP)编程入门教程】2.什么是类,什么是对象,类和对象这间的关系
类的概念:类是具有相同属性和服务的一组对象的集合.它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和服务两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...
- php面向对象(OOP)编程完全教程
摘自:http://www.php-note.com/article/detail/41 面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持.如何使用OOP的思想来进行P ...
- C语言面向对象风格编程
前言 本文略谈C面向对象风格编程,如何使用过程式语言去模拟面向对象的特性?C面向对象的方式和形式很多,不一而足,本文的代码形式是模拟部分C++面向对象关键词并赋予其特性,这种方式对于初级程序员比较好理 ...
- C++面向对象的编程
C++面向对象的编程 目录 对C++面向对象编程的理解 声明和定义类 声明和定义 构造函数 析构函数 静态成员和静态变量 类实例化对象 对象的浅复制和深复制 继承 单继承 多继承 虚函数 类模板 其他 ...
- Objective-C面向对象的编程
Objective-C面向对象的编程 目录 对面向对象编程思想的理解 类的声明和定义 类的声明和定义 对关键字super和self的理解 初始化函数 @property声明类成员 类的实例化 继承 组 ...
随机推荐
- Log4net使用(一)
LogHelper.cs using NLog; using NLog.Targets; namespace MyProject.Tool.Log { public class LogHelper { ...
- 学习Google Protocol buffer之语法
上一篇结尾的时候问了几个问题,其实主要就是这个protoBuffer协议的语法,弄清楚语法后边才好开展工作嘛,不然大眼而对小眼儿,互相不认识,就没法玩耍了.其实就是学习怎么用google提供的这套 p ...
- C语言字符串与数字相互转换
在C/C++语言中没有专门的字符串变量,通常用字符数组来存放字符串.字符串是以“\0”作为结束符.C/C++提供了丰富的字符串处理函数,下面列出了几个最常用的函数. ● 字符串输出函数puts. ● ...
- mybatis缓存学习笔记
mybatis有两级缓存机制,一级缓存默认开启,可以在手动关闭:二级缓存默认关闭,可以手动开启.一级缓存为线程内缓存,二级缓存为线程间缓存. 一提缓存,必是查询.缓存的作用就是查询快.写操作只能使得缓 ...
- git--- 拉取代码
- Hibernate原生SQL映射MySQL的CHAR(n)类型到String时出错
今天在用Hibernate通过原生SQL和ResultTransformer映射时,出现数据类型不匹配的错误.但是通过Entity映射,没有问题.在网上找了好多答案,终于解决了. 核心代码: Stri ...
- 简单解决ListView和ScrollView冲突,复杂情况仅供参考
ScrollView嵌套ListView冲突问题的最优解决方案 (转) 记录学习之用 项目做多了之后,会发现其实 ScrollView嵌套ListVew或者GridView等很常用,但是你也会发现各种 ...
- iOS不得姐项目--pop框架的初次使用
一.pop和Core Animation的区别 1.Core Animation的动画只能添加到layer上 2.pop的动画能添加到任何对象 3.pop的底层并非基于Core Animation,是 ...
- Edge Model
三种edge Step (阶梯) Ramp (坡) Roof 因为噪声的存在, ramp edge是最常见的. 一阶和二阶算子在ramp edge处的表现 一阶和二阶算子对噪声的敏感性 从上自下, 高 ...
- dede使用方法----调用导航
在这里,极力推荐学习dede的朋友们观看老李的零基础织梦仿站系列课程的视频,讲的超级棒的~~ 网址链接是:http://www.dede888.com/15daylessons.html. 好了,言归 ...