Python面向对象(一)

Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
 
一、面向对象技术简介
  • 类(class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

  • 数据成员:类变量或者实例变量用于处理类及其例对象的相关的数据。

  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写。

  • 实例变量:定义在方法中的变量,只作用于当前实例的类。

  • 继承:即一个派生类继承基类的字段和方法。继承也允许把一个派生类的对象作为一个基类的对象对待。例如,有这样一个设计:一个dog类型的对象派生自animal类,这是模拟“是一个”关系(例如,dog是一个animal)

  • 实例化:创建一个类的实例,类的具体对象。

  • 方法:类中定义的函数

  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

 
二、什么是面向对象的程序设计及为什么要有它

面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西。

优点是:极大的降低了程序的复杂度,复杂的问题简单化,流程化

缺点是:扩展性差,一套流水线或者流程就是用来解决一个问题,生产汽水的流水线无法生产汽车,即便是能,也得大改,改一个组件,牵一发而动全身。

应用场景:一旦完成基本很少改变的场景,著名的例子有Linux內核,git,以及Apache HTTP Server等。

 

面向对象的程序设计的核心是对象(上帝式思维),对象是特征(变量)与技能(函数)的结合体,要理解对象为何物,必须把自己当成上帝,上帝眼里世间存在的万物皆为对象,不存在的也可以创造出来。

在现实世界中:对象----(共同的特征与技能)--->类

在程序中:先定义类----(实例化)----->对象

应用场景:需求经常变化的软件,一般需求的变化都集中在用户层,互联网应用,企业内部软件,游戏等都是面向对象的程序设计大显身手的好地方

优点是:解决了程序的扩展性。对某一个对象单独修改,会立刻反映到整个体系中,如对游戏中一个人物参数的特征和技能修改都很容易。

缺点:可控性差;编程的复杂度远高于面向过程,不了解面向对象而立即上手基于它设计程序,极容易出现过度设计的问题。一些扩展性要求低的场景使用面向对象会徒增编程难度,比如管理linux系统的shell脚本就不适合用面向对象去设计,面向过程反而更加适合

 面向对象的设计并不是全部。对于一个软件质量来说,面向对象的程序设计只是用来解决扩展性。

 

三、类和对象
"""
类即类别、种类,是面向对象设计最重要的概念,对象是特征与技能的结合体,而类则是一系列对象相似的特征与技能的结合体。
那么问题来了,先有的一个个具体存在的对象(比如一个具体存在的人),还是先有的人类这个概念,这个问题需要分两种情况去看
在现实世界中:先有对象,再有类
世界上肯定是先出现各种各样的实际存在的物体,然后随着人类文明的发展,人类站在不同的角度总结出了不同的种类,如人类、动物类、植物类等概念
也就说,对象是具体的存在,而类仅仅只是一个概念,并不真实存在
在程序中:务必保证先定义类,后产生对象
这与函数的使用是类似的,先定义函数,后调用函数,类也是一样的,在程序中需要先定义类,后调用类
不一样的是,调用函数会执行函数体代码返回的是函数体执行的结果,而调用类会产生对象,返回的是对象
 
"""
概述

3.1 什么是对象,什么是类

Python中一切皆为对象,且Python统一了类与类型的概念,类型就是类

类定义

语法格式如下:

1.
class 类名:    # 类名首字母大写
    '''注释'''
    类体
2.
class ClassName:
    <statement-1>
    .
    .
    .
    <statement-N>

类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。

 

类对象

类对象支持两种操作:属性引用和实例化

属性引用使用和Python中所有的属性引用一样的标准语法:obj.name

类对象创建后,类命名空间中所有的命名都是有效属性名。所以如果类定义是这样的:

class Myclass:
    """一个简单的类实例"""
    i=12345
    def f(self):
        return 'hello world'
# 实例化类
x=Myclass()
# 访问类的属性和方法
print("MyClass 类的属性i为:",x.i)
print("MyClass 类的方法f输出为:",x.f())

以上创建了一个新的类实例并将对象赋给局部变量x,x为空的对象。

输出结果为:

MyClass 类的属性i为: 12345
MyClass 类的方法f输出为: hello world

 

很多类都倾向于将对象创建为有初始状态的。因此类可能会定义一个名为__init__()的特殊方法(构造方法),像下面这样:

 
def __init__(self):
        self.data = []    #定义空列表

当然,__init__()方法可以有参数,参数通过__init__()传递到类的实例化操作上。例如:

class Teacher:
    school='oldboy'    #定义对象的共同特征
    def __init__(self,name,age):    #用户创建对象传入的参数
        self.name=name
        self.age=age
    def talk(self):
        print('is talking')
    def walk(self):
        print('is walking')
t1=Teacher('egon',23)   # 实例化:__init__(t1,'egon',23)
t2=Teacher('alex',32)   # 实例化:__init__(t2,'alex',32)
self代表类的实例。而非类
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,按照惯例它的名称是self。
# 属性引用
# 数据属性
# print(Teacher.school)
# print(Teacher.__dict__)
# 函数属性
# print(Teacher.walk)
# print(t1.name)
# print(t2.talk)

  

类的方法

在类的内部,使用def关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数,self代表的是类的实例。

#类定义
class people:
    #定义基本属性
    name = ''
    age = 0
    #定义私有属性,私有属性在类外部无法直接进行访问
    __weight = 0
    #定义构造方法
    def __init__(self,n,a,w):
        self.name = n
        self.age = a
        self.__weight = w
    def speak(self):
        print("%s 说: 我 %d 岁。" %(self.name,self.age))
# 实例化类
p = people('runoob',10,30)
p.speak()

类有两种作用:属性引用和实例化

1)属性引用(类名.属性)

class Student:
    school = 'oldboy'
    def __init__(self,name,age):
        #只用来初始化的,并且一定不能有返回值
        self.name=name
        self.age=age
    def study(self):
        print('%s is studying' %self.name)

s1=Student('egon',84)    #步骤一:造出对象s1  #步骤二:初始化s1,把s1,'egon',84传给__init__
__init__只用来初始化函数的,并且一定不能有返回值
数据属性、函数属性:
print(Student.school)    #引用类的数据属性    #输出结果:oldboy
print(Student.study)    #引用类的函数属性    #输出结果:<function Student.study at 0x00000149F72B7620>

对象的修改、删除和添加:

#修改
Student.school='偶的博爱'    #修改变量school的值
print(Student.school)        #输出结果:偶的博爱

#删除
del Student.school    #删除school属性的值
print(Student.__dict__)    #类名.__dict__:查出的是一个字典,key为属性名value为属性值

输出结果:(上面为没删除之前,删除之后,通过__dict__可查看到类的信息)
{'__module__': '__main__', 'school': '偶的博爱', '__init__': <function Student.__init__ at 0x000001BB20097598>, 'study': <function Student.study at 0x000001BB20097620>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
{'__module__': '__main__', '__init__': <function Student.__init__ at 0x000001BB20097598>, 'study': <function Student.study at 0x000001BB20097620>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}

#添加
Student.x=6666666666666    #添加一个属性x=6666666666666
print(Student.x)    
print(Student.__dict__)    #可查看到字典里多了一值

只要是对象绑定方法都会字典传值,把自己传给函数

s1.study()   #调用函数 egon is studying

 补充:

类有两种属性:数据属性和函数属性
1 类的数据属性是所有对象共享的
2 类的函数属性是绑定给对象用的

类的数据属性是所有对象共享的,id都一样
类的函数属性是绑定给对象使用的,obj.method称为绑定方法,内存地址都不一样

ps:id是python的实现机制,并不能真是反映内存地址,如果有内存地址,还是以内存地址为准

在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类(基类),最后都找不到就抛出异常

类中定义的函数(没有被任何装饰器装饰的)是类的函数属性,类可以使用,但必须遵循函数的参数规则,有几个参数需要传几个参数

类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象指向都是相同的功能,但是绑定到不同的对象就是不同的绑定方法

强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)
 
2)我们定义的类的属性到底存在哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
 
3)特殊的类属性
类名.__name__ # 类的名字(字符串)
类名.__doc__    # 类的文档字符串
类名.__base__    # 类的第一父类
类名.__bases__ # 类所有父类构成的元组
类名.__dict__ # 类的字典属性
类名.__module__ # 类定义所在的模块
类名.__class__ # 实例对应的类(仅新式类中)
4)对象/实例
对象/实例本身只有数据属性,但是Python的class机制会将类的函数绑定到对象上,称为对象的方法,或者叫绑定方法,绑定方法唯一绑定一个对象,同一个类的方法绑定到不同的对象上,属于不同的方法,内存地址都不会一样
对象的绑定方法的特别之处在于:obj.func()会把obj传给func的第一个参数
 
5)类名称空间与对象/实例名称空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
而类有两种属性:数据属性和函数属性
其中类的数据属性是共享给所有对象的,而类的函数属性是绑定到所有对象的
 
创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
在obj.name会优先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类,最后都找不到就抛出异常
 
6)对象之间的交互
class Garen:        #定义英雄盖伦的类,不同的玩家可以用它实例出自己英雄;
    camp='Demacia'  #所有玩家的英雄(盖伦)的阵营都是Demacia;
    def __init__(self,nickname,aggressivity=58,life_value=455): #英雄的初始攻击力58...;
        self.nickname=nickname  #为自己的盖伦起个别名;
        self.aggressivity=aggressivity #英雄都有自己的攻击力;
        self.life_value=life_value #英雄都有自己的生命值;
    def attack(self,enemy):   #普通攻击技能,enemy是敌人;
        enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。

我们可以仿照garen类在创建一个Riven类

class Riven:
    camp='Noxus'  #所有玩家的英雄(锐雯)的阵营都是Noxus;
    def __init__(self,nickname,aggressivity=54,life_value=414): #英雄的初始攻击力54;
        self.nickname=nickname  #为自己的锐雯起个别名;
        self.aggressivity=aggressivity #英雄都有自己的攻击力;
        self.life_value=life_value #英雄都有自己的生命值;
    def attack(self,enemy):   #普通攻击技能,enemy是敌人;
        enemy.life_value-=self.aggressivity #根据自己的攻击力,攻击敌人就减掉敌人的生命值。

实例出俩英雄

>>> g1=Garen('草丛伦')
>>> r1=Riven('锐雯雯')

交互:锐雯攻击草伦,反之一样

>>> g1.life_value
455
>>> r1.attack(g1)
>>> g1.life_value
401 

 

练习一堆类:
# 老师类
class Teacher:
    school='oldboy'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talk(self):
        print('is talking')
    def walk(self):
        print('is walking')
t1=Teacher('egon',23)   # 实例化:__init__(t1,'egon',23)
t2=Teacher('alex',32)   # 实例化:__init__(t2,'alex',32)

  

# 学生类
class Student:
    job='student'
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def talk(self):
        print('is talk')
    def eat(self):
        print('is eating')
s1=Student('buer',20)    # 实例化:__init__(s1,'buer',20)
s2=Student('dongbei',22) # 实例化:__init__(s2,'dongbei',22)
print(s1)

  

# 狗类
class Dog:
    bottle='dog'
    def __init__(self,name,color):
        self.name=name
        self.color=color
    def talk(self):
        print('汪汪汪')
    def eat(self):
        print('dog good')
d1=Dog('哈士奇','blank')   # 实例化:__init__(d1,'哈士奇','blank')
d2=Dog('泰迪','brown')    # 实例化:__init__(d2,'泰迪','brown')

  

# 猪类
class Pig:
    bottle='big'
    def __init__(self,name):
        self.name=name
    def talk(self):
        print('哼哼哼')
    def eat(self):
        print('pig good')
p1=Pig('xiangzhu')  # 实例化:__init__(p1,'xiangzhu')
p2=Pig('huazhu')    # 实例化:__init__(p2,'huazhu')
print(p1)

  

# 动物类
class Animal:
    local='zoo'
    def __init__(self,name,kind):
        self.name=name
        self.kind=kind
    def talk(self):
        print('people do not know what to say')
    def pull(self):
        print('no need for toilet')
a1=Animal('xingxing','monkey')
a2=Animal('fenda','panda')

  

posted @ 2017-08-16 20:05  申不二  阅读(394)  评论(3编辑  收藏  举报