一、面向对象与面向过程

  面向对象与面向过程是两种不同的编程范式,范式指的是按照什么方式去编程、去实现一个功能。不同的编程范式本质上代表对各种不同类型的任务采取不同的解决问题的思路。

1、面向过程编程

  角色是执行者,把一个项目按照一定的顺序,从头到尾一步步执行下去。这种思想好理解,但只要前面一个步骤变了,后面的步骤也要跟着变,维护起来比较麻烦。

2、面向对象编程

  角色是指挥者,把一个项目分成一个个小的部分,每个部分负责一方面的功能,整个项目由这些部分组合而成一个整体。类似一个机关,分为各个职能部门,只要符合一定的前提就行。面向对象的思想适合多人分工合作。

  面向对象是包含面向过程思路的,比如定义类中的方法,每个小方法、小功能还是面向过程的的思想。

  面向对象与面向过程的主要区别就是:面向对象可以使程序更加容易更改和扩展。

二、面向对象的特性

1、类

  Class,相当于一个种类、一个模型。一个类就是对一类拥有相同属性的对象的抽象、蓝图、原形。在类中定义了这些对象都具备的属性、共同的方法。

2、对象(实例)

  Object,根据模型造出来的具体的东西。一个对象就是一个类实例化后实例。一个类必须经过实例化后才能在程序中调用,一个类可以实例化多个对象,每个对象也可以有不同的属性。(对象就是实例,两者是一个意思)

3、实例化

  初始化一个类,创造一个对象。把一个类变成一个具体的对象的过程,叫做实例化。

4、属性

  属性就是类里面的一个变量,有类属性(类变量)和实例属性(实例变量)两种。类属性是在定义的时候就有的,实例属性是在实例化的时候才产生的变量。举个例子来说明类属性于实例属性:

  类属性(类变量):公共的变量,每个实例都可以用。直接通过“类名.XXX”来进行调用和修改,不需要实例化

  实例属性(实例变量):必须先进行实例化,然后通过“实例名.XXX”来进行调用和修改。

  下面简单定义一个类来说明以上概念,类的定义使用class关键字,类名的首字母大写。

 class Person():  # 经典类,新式类为:class Person(object):
hand = 2 # 类属性/静态字段
def __init__(self,name): # 构造函数,类在实例化的时候自动执行的函数
# self代表的是实例化之后的对象
self.name = name # 实例属性/普通字段
self.nose = 1 # 实例属性/普通字段
print('开始创造机器人。。。')
def driver(self): # 实例方法/普通方法
print('%s开车中。。'%self.name)
self.eat() # 调用类里面的方法
def fly(self): # 实例方法/普通方法
print('%s,飞吧。。'%self.name) # 获取类里面的变量
def eat(self): # 实例方法/普通方法
print('%s吃吧,管饱'%self.name) # 类在用的时候,首先需要实例化
zlj = Person('张流量') # 实例化:类名+括号
print(zlj.name) # 调用实例属性
print(zlj.hand) # 调用类属性
zlj.hand = 5 # 不会改变类变量,只影响实例里面的变量
print(zlj.hand) #
print(Person.hand) # 2,上面虽然通过实例修改了变量,但不影响类变量,只是zlj这个实例里面的变量发生了修改
zlj.sex = '男' # 为实例增加实例属性
print(zlj.sex) # 男
zlj.driver() # 调用类方法
zlj.fly() # 调用类方法
dcg = Person('董春光') # 实例化dcg
print(dcg.hand) #
Person.hand = 10 # 修改类变量
print(dcg.hand) #
print(zlj.hand) # 5,修改类变量发生在修改实例变量之后,所以实例变量的值不再发生改变

5、方法

    方法就是类的功能,是定义在类里面的函数

  (1)构造方法:__init__

      实例化后会自动调用的方法,但不是每个类都必须写的,一个类中可以没有构造方法。

  (2)实例方法/普通方法:self

      保存在类中,由对象来调用,实例化后才能使用的方法。

  (3)静态方法():@staticmethod

      a、静态方法就是一个普通的函数,只不过写在类里面而已

      b、它用不了本类中的类属性(变量)、类方法、实例属性(变量)、实例方法

      c、保存在类中,通过类名+静态方法名()直接调用

      d、也可以通过实例化后,通过实例调用

  (4)类方法(cls):@classmethod

      a、不用实例化就可以直接调用

      b、它可以通过cls使用类变量

      c、它不能调用实例变量和实例方法

      d、不想实例化的时候,可以把方法定义成类方法

      e、也可以通过实例化后,通过实例调用

  (5)属性方法:@property

      看起来很像属性的一个方法,将没有入参的函数变为一个变为一个属性方法(类似于变量),结果是函数的返回值

 class Baby(object):
nationality = 'China' # 类变量,公共变量,每个实例都可以用
def __init__(self): # 构造方法,类在实例化的时候自动执行的函数
self.name = 'niu' # 实例变量,必须实例化才能调用
print('init构造方法')
def my(self): # 实例方法,必须实例化才能调用
self.sex = 'male' # 实例变量,必须实例化才能调用
print('self,实例方法')
@staticmethod # 静态方法
def xh(): # 静态方法括号里面不用写self
# self.name # 报错,不能调用类中其他的实例变量
# self.my() # 报错,不能调用类中其他的实例变量
print('staticmethod')
@classmethod # 类方法,不用实例化就可以直接调用
def xm(cls): # cls代表的就是Baby类
print('classmethod')
print(cls.nationality) # 可以调用类变量
# cls.name # 报错,不能调用类中其他的实例变量
# cls.my() # 报错,不能调用勒种其他的实例方法
@property # 属性方法,直接返回函数执行结果
def AAA(self):
return 98 # 实例方法
Zll = Baby() # 实例化,实例化后自动执行构造函数
Zll.my() # 实例方法实例化后才能调用 # 静态方法:
# 1、就是一个普通函数,只不过是写在类里面而已
# 2、它用不了类变量、类方法、实例变量、实例方法
# 3、可以不用实例化,直接调用类名调用
# 4、也可以通过实例化后,通过实例调用
Baby.xh() # 不用实例化直接用类名调用类方法
a = Baby() # 也可以通过实例化后,通过实例调用
a.xh()
# 类方法:不想实例化的时候可以定义成类方法
# 1、不用实例化就可以直接调用
# 2、它可以通过cls使用类变量
# 3、它不能调用这个类里面的其他实例方法和实例变量
# 4、也可以通过实例化后,通过实例调用
Baby.xm() # 不用实例化直接用类名调用类方法
b = Baby() # 也可以通过实例化后,通过实例调用
b.xm() # 属性方法
Dcg = Baby()
print(Dcg.AAA) # 调用属性方法不用加括号

属性方法还有另外一种写法,如下:

 # 属性方法第二种方式
class Foo():
def f1(self):
return 112
def f2(self,name): # 必须有参数
print(name)
def f3(self):
print('f3')
per = property(fget=f1,fset=f2,fdel=f3,doc='介绍&说明') obj = Foo() # 实例化
ret = obj.f1() # 获取f1的返回值
print(ret)
obj.per = 'niu' # 传参数给f2并调用f2
del obj.per # 调用f3

6、继承

  一个类可以派生出子类,在父类里面定义的属性和方法自动被子类继承,继承是为了代码重用。并且,子类可以重写父类的方法。Python3中经典类和新式类的多继承都是广度优先。但在Python2中,经典类和新式类的多继承是有区别的:经典类的多继承是深度优先,新式类的多继承是广度优先。

 class Father(object):  # 父类
def __init__(self):
self.money = 1000000
self.house = '5环20套'
def sing(self):
print('唱歌')
def dance(self):
print('跳广场舞')
def mf(self):
print('找朋友')
class Son(Father): # 继承类:将父类名写在括号里
def dance(self):
self.house = '2环1套'
print('跳霹雳舞') # 通过继承类调用父类中的方法和变量
m = Son() # 实例化
print(m.money) # 调用父类中的实例变量
m.sing() # 调用父类中的实例方法
m.dance() # 子类和父类中都存在的方法则用子类中的方法
print(m.house) # 子类和父类中都存在的变量则用子类中的变量

重写父类的方法:

  (1)父类方法没用,需要重写

  (2)父类方法不够完善,想给这个方法在原有的基础上添加一些功能

 class Zll():
pass class Dcg():
def smile(self):
print('喔喔喔') class Lw():
def smile(self):
print('啊啊啊') class Xz(Zll,Dcg,Lw): # 子类可以继承多个父类
def smile(self): # 重写父类的方法
Lw().smile() # 调用父类,指定哪个父类
super(Xz,self).smile() # 自动找到父类,先找到哪个类用哪个类
print('呵呵呵') A = Xz()
A.smile()

多继承:

(1)A作为B和C共同的父类

 class A(object):  # 新式类
def x(self):
print('A')
class B(A):
pass
class C(A):
def x(self):
print('C')
class D(B,C):
pass S = D()
S.x() # C
# A作为B和C共同的父类时,是按D→B→C→A的顺序来找,遇到共同的父类时先不到父类中去找,先换到另外一个分支查找,找不到再到父类中去找

(2)A只作为B的父类

 class A(object):  # 新式类
def x(self):
print('A')
class B(A):
pass
class C():
def x(self):
print('C')
class D(B,C):
pass S = D()
S.x() # A
# A只作为B的父类时,是按D→B→A→C的顺序来找,先找完一个分支,再找另外一个分支

(3)多继承中构造函数的调用

 class A(object):  # 新式类
def __init__(self):
print('A.init')
class B(A):
def __init__(self):
print('B.init')
A.__init__(self)
def x(self):
print('x')
self.y() # 根据继承关系从头开始找,先从C中找,再从B中找
def y(self):
print('x--y')
class C():
def y(self):
print('y')
class D(C,B):
pass S = D() # 实例化时只会调用一次构造函数,本类找不到就到父类中找,但如果本类中找到则不再到父类中找构造函数
S.x() # 调用B中的x时,self.y()不是直接调用B中的y,而是要根据继承关系先从C中找,如果C中没有,再从B中找,所以结果是x和y,不是x和x--y

7、封装

  把一些功能的实现细节隐藏,但类中对数据的赋值、内部调用对外部用户却是透明的,使类变成一个胶囊或容器,里面包含着类的数据和方法(比如说创造一个人,把身体内部的心肝脾肺肾都封装起来了,其他人只能直接找这个人而看不到里面有上面东西)。

8、多态

  对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。

  多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。一种接口,多种实现。

 class Animal(object):  # 父类
def __init__(self, name):
self.name = name
class Dog(Animal): # 狗类,有叫的方法
def cry(self):
print('狗 [%s] 汪汪汪' % self.name)
class Cat(Animal): # 猫类,有叫的方法
def cry(self):
print('猫 [%s] 喵喵喵' % self.name)
def cry(obj): # 定义一个函数,去调用传进来的实例的cry方法
obj.cry() d1 = Dog('大黄') # 实例化狗
d2 = Dog('小黄') # 实例化狗
c1 = Cat('小白') # 实例化猫
c2 = Cat('小黑') # 实例化猫
cry(d1) # 把对象d1传进来
cry(d2) # 把对象d2传进来
objs = [d1, d2, c1, c2] # 把上面实例化的对象都放到一个list里面
for obj in objs: # 循环统一调用
cry(obj)

三、本类对象

  类中的self代表的是本类对象,也就是实例化后的对象。因为函数里面的变量都是局部变量,出了函数就不能使用,用self绑定之后,在类中任何地方都能随便使用(self.XXX)。

 class Baby:
def __init__(self,name):
#name = name # 局部变量,出了函数就失效
self.name = name # 在类中self.name可以随便用了
print('self的内存地址', id(self))
def cry(self):
print('%s在哭'%self.name) # self.name在类中其他方法可以使用
Zll = Baby('张流量') # 实例化时将Amy的地址给self
print('实例的内存地址',id(Zll)) # 与实例化时self的内存地址一致
Zll.cry()
# 通过运行发现self的内存地址和实例的内存地址是一样的,说明self代表的就是实例化后的对象Zll

四、构造函数与析构函数

1、构造函数

  类在实例化时自动执行的函数,但类中不是必须包含构造函数的。

  实例化时只有构造函数会自动执行,其他函数不会被执行。

 class Baby(object):
def __init__(self): # 构造函数,类在实例化的时候自动执行的函数
self.name = '牛牛' # 实例变量,必须实例化才能调用
def my(self): # 实例方法,必须实例化才能调用
self.sex = '男' # 实例变量,必须实例化才能调用 Zll = Baby()
print(Zll.name) # 实例化时构造函数自动执行
print(Zll.sex) # my方法未被执行,所以会报错--'Baby' object has no attribute 'sex'

解决Zll.sex报错有两种方式:

(1)在构造函数中调用一次my函数,如下:

 class Baby(object):
def __init__(self): # 构造函数,类在实例化的时候自动执行的函数
self.name = '牛牛' # 实例变量,必须实例化才能调用
self.my() # 在构造函数中调用一次my方法,实例化时会自动执行
def my(self): # 实例方法,必须实例化才能调用
self.sex = '男' # 实例变量,必须实例化才能调用 Zll = Baby()
print(Zll.name) # 实例化时构造函数自动执行
print(Zll.sex) # 实例化时自动调用了一次my函数

(2)实例化后,先调用一次my函数,再使用my函数下的实例变量,如下:

 class Baby(object):
def __init__(self): # 构造函数,类在实例化的时候自动执行的函数
self.name = '牛牛' # 实例变量,必须实例化才能调用
def my(self): # 实例方法,必须实例化才能调用
self.sex = '男' # 实例变量,必须实例化才能调用 Zll = Baby()
print(Zll.name) # 实例化时构造函数自动执行
Zll.my() # 调用一次my方法
print(Zll.sex)

2、析构函数

  实例被销毁的时候执行,但不是必须的。

  一般可用于测试用例执行完毕后的关闭连接、关闭数据库、删除测试数据等操作。

例子:操作Mysql数据库

 import pymysql
class MyDb(object):
def __init__(self,host,user,db,passwd,
port=3306,charset='utf8'): # 构造函数
try:
self.conn = pymysql.connect(
host=host,user=user,passwd=passwd,port=port,db=db,charset=charset,
autocommit=True # 自动提交
)
except Exception as e:
print('数据库连接失败!:%s'%e)
else:
self.cur = self.conn.cursor(cursor=pymysql.cursors.DictCursor) def __del__(self): # 析构函数,实例被销毁的时候执行
self.cur.close()
self.conn.close()
print('数据库连接关闭') def ex_sql(self,sql):
try:
self.cur.execute(sql)
except Exception as e:
print('sql语句有问题:%s'%sql)
else:
self.res = self.cur.fetchall()
return self.res my = MyDb('118.24.3.40','jxz','jxz','')
my.ex_sql('select * from stu;')
print(my.res) # 可以用实例属性取值
print(my.ex_sql('select * from stu;')) # 也可以用实例方法的返回值
print('我是最后一行代码') # 执行完最后这行代码后再执行析构函数

五、私有变量&私有方法

出了类以后就不能再使用的变量和方法,被称为私有变量、私有方法。

有些重要的信息不想被调用,可以加两个下划线"__",将变量或者方法变为私有。

 # 私有方法 & 私有变量:出了类不能用
class Redis(object):
__table = 'user' # 私有类变量
def __init__(self):
self.__host = '127.0.0.1' # 私有变量
self.port = 6379
def __close(self): # 私有方法
print('私有方法')
def open(self):
print('实例方法')
print(Redis.__table) # 类内部可以调用私有类变量
self.__close() # 类内部可以调用私有方法
return self.__host # 类内部可以调用私有变量
@staticmethod
def stac():
return Redis.__table m = Redis()
print(m.__host) # 报错,没有__host这个属性,私有变量出类后不能再使用
m.__close() # 报错,没有这个方法,,私有方法出类后不能再使用
m.__table # 报错,没有__table这个属性,私有变量出类后不能再使用
print(m.port) # 打印出:6379
m.open() # 把私有方法放入实例方法中,通过调用实例方法可以拿到私有方法的返回值
Redis.stac() # 通过静态方法还是可以拿到类的私有变量
# 和实例方法一样,静态方法和类方法同样也可以是私有的,这里就不再举例
# 存在继承关系的类中,子类不能调用父类的私有变量和私有方法,如果想访问需要在父类中定义一个共有的方法,然后把私有变量和方法放进去

例子:操作Redis数据库

 # 封装redis操作类
import redis
class My(object):
def __init__(self):
self.__host = '127.0.0.1' # 私有变量
self.__port = 6379 # 私有变量
self.__passwd = '' # 私有变量
self.__db = 1 # 私有变量
try:
self.r = redis.Redis(host=self.__host,port=self.__port,password=self.__passwd,db=self.__db)
except Exception as res:
print('redis连接失败..【%s】'%res)
# 这时并不会去连redis
# 所以捕捉不到数据库连接失败的异常,这里写的捕捉异常没有意义,可以不写
def __close(self): # 私有方法
print('close') def str_get(self,name): # str类型get
res = self.r.get(name)
if res:
return res.decode()
return None def str_set(self,name,value,time=None): # str类型set
self.r.set(name,value,time) def str_delete(self,name): # str类型的删除key
# res = self.r.get(name)
res = self.r.exists(name) # 判断redis数据库是否存在name这个key
if res:
self.r.delete(name)
print('删除成功')
else:
print('%s不存在'%name) def hash_get(self,name,key): # hash类型获取单个key
res = self.r.hget(name,key)
if res:
return res.decode()
return None def hash_set(self,name,key,value): # hash类型set
self.r.hset(name,key,value) def hash_getall(self,name): # hash类型获取key里面的所有数据
dic = {}
res = self.r.hgetall(name)
if res:
for key,value in res.items():
dic[key.decode()] = value.decode()
return dic
return None def hash_del(self,name,key): # 删除某个hash里面小key
res = self.r.hget(name,key)
if res:
self.r.hdel(name,key)
print('删除成功')
else:
print('%s不存在'%name) def clean_redis(self): # 清理redis
# self.r.flushdb() # 清空redis数据库
res = self.r.keys()
for key in res:
self.r.delete(key)
print('清空redis数据库成功') m = My()
m.str_set('Kity','famale')
print(m.str_get('Kity'))
m.str_delete('Kity')
m.hash_set('toy','car','red')
m.hash_set('toy','ball','blue')
print(m.hash_get('toy','car'))
print(m.hash_get('toy','car'))
m.hash_del('toy','car')
m.clean_redis()

Python学习之==>面向对象编程(一)的更多相关文章

  1. Python学习之==>面向对象编程(二)

    一.类的特殊成员 我们在Python学习之==>面向对象编程(一)中已经介绍过了构造方法和析构方法,构造方法是在实例化时自动执行的方法,而析构方法是在实例被销毁的时候被执行,Python类成员中 ...

  2. 从0开始的Python学习014面向对象编程

     简介 到目前为止,我们的编程都是根据数据的函数和语句块来设计的,面向过程的编程.还有一种我们将数据和功能结合起来使用对象的形式,使用它里面的数据和方法这种方法叫做面向对象的编程. 类和对象是面向对象 ...

  3. Python学习--10 面向对象编程

    面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 本节对于面向对象的概念不做 ...

  4. Python 中的面向对象编程

    面向对象编程(Object-oriented programming, OOP)是一种基于对象概念的编程范式,可包含属性(attribute)形式的数据以及方法(method)形式的代码.另一种对 O ...

  5. python学习_数据处理编程实例(二)

    在上一节python学习_数据处理编程实例(二)的基础上数据发生了变化,文件中除了学生的成绩外,新增了学生姓名和出生年月的信息,因此将要成变成:分别根据姓名输出每个学生的无重复的前三个最好成绩和出生年 ...

  6. Python:笔记(3)——面向对象编程

    Python:笔记(3)——面向对象编程 类和面向对象编程 1.类的创建 说明:和Java不同的是,我们不需要显示的说明类的字段属性,并且可以在后面动态的添加. 2.构造函数 构造函数的功能毋庸置疑, ...

  7. Python学习day40-并发编程(终)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  8. Python学习day39-并发编程(各种锁)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  9. Python学习day38-并发编程(线程)

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

随机推荐

  1. C#基础知识之理解Cookie和Session机制

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  2. u-boot initf_bootstage函数分析

    这篇博客主要分析 init_sequence_f 函数指针数组中的initf_bootstage函数: static int initf_bootstage(void){    bool from_s ...

  3. ESP-8266 串口通信(Serial)

    ESP8266的串口通信与传统的Arduino设备完全一样.除了硬件FIFO(128字节用于TX和RX)之外,硬件串口还有额外的 256字节的TX和RX缓存.发送和接收全都由中断驱动.当FIFO/缓存 ...

  4. Mac SIP系统完整性保护如何关闭

    方法/步骤1: 打开Mac终端输入命令:csrutil status 它会显示关闭的话是disable,开启的话是enabled.默认情况下是开启的所以要关闭. 方法/步骤2: 点击桌面的apple ...

  5. GDOI2017总结

    前言 大概在两个星期前,由于会有一堆人因为限人数的问题而被卡掉,当时那个人心惶惶啊,搞到我们心惊胆战,茶饭不安. 话说某日,jacky36当众表示,辣鸡余可灿,把我卡掉啦,B~(屏蔽不良言语).余可灿 ...

  6. Hibernate方法save、update、merge、saveOrUpdate及get和load的区别

    在看这几个方法区别之前,有必要了解hibernate实体对象的三种状态,点击查看 http://www.cnblogs.com/Y-S-X/p/8345754.html 一.update 和 merg ...

  7. org.springframework.web.servlet.view.ContentNegotiatingViewResolver

    restful服务中一个重要的特性就是一种资源可以有多种表现形式,在springmvc中可以使用ContentNegotiatingViewResolver这个视图解析器来实现这种方式. 描述资源的三 ...

  8. node.js模块中exports和module.exports的区别

    Node应用由模块组成,采用CommonJS模块规范. 根据这个规范,每个文件就是一个模块,有自己的作用域.在一个文件里面定义的变量.函数.类,都是私有的,对其他文件不可见. CommonJS规范规定 ...

  9. 18.二叉树的镜像(python)

    题目描述 操作给定的二叉树,将其变换为源二叉树的镜像. class Solution: # 返回镜像树的根节点 def Mirror(self, root): # write code here if ...

  10. 部署jumpserver

    参考:https://jumpserver.readthedocs.io/zh/master/setup_by_centos7.html yum update -y systemctl start f ...