第12篇,面向对象编程

一些概念

  • 围绕函数来设计程序的过程,叫做面向过程编程;
  • 而面向对象编程,就是将数据与功能进行组合,并将其包装在被称为对象的物体内。
  • 类与对象是面向对象编程的两个重要方面。一个类(class)能够创建新的类型(type)对象(object)就是类的实例(instance).
  • 对象可以使用它的普通变量来存储值,这个从属于对象或类的变量叫做字段Field
  • 对象还可以使用累的某些函数来做一些操作,这种函数叫做类的方法Method.
  • 字段和方法统称类的属性
  • 字段有两种类型:属于一个类的各个实例或对象的叫做实例变量Instance Variables,属于某一个类的叫做类变量Class Variables

self

self用于区分类方法与普通。
在类方法中,必须有一个额外的名字来添加到参数列表的开头,但是我们不用调用这个功能时就为这个参数进行赋值,Python会为它提供。这种特定的变量引用的是对象本身,被特定命名为self.
于是,我们可以知道,就算我们定义一个没有参数的类方法,它也是会有一个特定的参数self.

(关于self不理解的,可以先放一下,等把接下来的学习一下之后再回过来看就会好很多)

创建一个类和方法并使用

# 创建一个类,使用 'class + 类名'的形式
class MyFirstClass:
    # 类方法
    def Class_Method_Test(self):
        print('我是一个类方法')

# 实例化一个对象并输出相关信息
first = MyFirstClass()
print(first)

# 调用实例方法
first.Class_Method_Test()

输出结果

<__main__.MyFirstClass object at 0x1010ea438>
我是一个类方法

Process finished with exit code 0

具体的请参考注释。

__init__方法

__init__方法会在一个类被实例化时立即调用,请参考下面的代码

# 使用__init__方法

class MyClassDemo:
    # 调用init方法,并设置name,name2两个传入参数
    def __init__(self,name,name2):
        # 创建新字段name和myName接收和传递参数name、name2的值
        print('3')
        self.name = name
        self.myName = name2
    def getName(self):
        # 在这里使用上面所创建新字段name、myName传递过来的值
        print('4')
        print('The name is:',self.name)
        print('Other name is:',self.myName)

# 实例化对象,调用__init__方法,并传入两个参数的值
print('1')
demo = MyClassDemo('Ultraman Zero.','Ultraman Seven.')

# 调用类的方法
print('2')
demo.getName()

输出结果

1
3
2
4
The name is: Ultraman Zero.
Other name is: Ultraman Seven.

Process finished with exit code 0

从上面的输出,可以看出程序运行的次序为:实例化一个对象 --> 调用__init__方法 --> 实例对象调用类方法
说明请参考注释。

类变量与对象变量

字段有两种形式:类变量对象变量
类变量是共享的,它可以被这个类的所有实例对象使用,当一个实例对象对它做出变化时,这种变化将会体现到这个类的所有实例对象中。
对象变量由类的每一个单独的实例变量拥有,一个类的实例变量对它做出改变时,其它类的实例对象不会发生变化。对象变量不是共享的,每个对象都有属于它自己的字段的副本。
请参考下面的例子

class Reboot:
    """ 创建一个类变量,用于计算数量 """
    Population = 0;

    """ 
    创建机器人的接口
    每次创建一个机器人的实例对象,Population的值就会+1 
    """
    def __init__(self,name):
        self.rebootName = name
        print(self.rebootName,' is Initialazing......')
        Reboot.Population += 1

    # 每次销毁一个机器人,Population的数量就会-1
    def reboot_die(self):
        print(self.rebootName,' is being destorying....')
        Reboot.Population -= 1
        print('Now Reboot population  = ',Reboot.Population)
        if Reboot.Population < 1:
            print('We have no Reboot.')
        else:
            print('We still have {:d} Reboots'.format(Reboot.Population))

    def say_hi(self):
        print("Hello,I'm {}".format(self.rebootName))

    # 使用装饰器Decorator来将方法标记为类方法
    # 使用装饰器等价于调用  how_manay=classmethod(how_manay)
    @classmethod
    def how_manay(cls):
        print("We have {:d} reboots".format(cls.Population))


reboot0 = Reboot('Yiwa')
reboot0.say_hi()

print('\n')
reboot1 = Reboot('Yiwa1')
reboot1.say_hi()

print('\n')
reboot0.reboot_die()
Reboot.how_manay()
  • 说明,如上代码,我们除了可以使用Reboot.Population之外,还可以使用self.__class_.Population,因为每个对象都通过self.__class_.Population来引用它的类。
  • 还有,我们只能通过self来引用同一对象的变量和方法。这种叫做属性引用。
  • 在Python中,所有类成员,包括数据成员都是公开的,所有方法都是虚拟的。
  • 我们还可以通过在数据成员名称前面加"__"双下划线前缀,这是Python会使用命名调整来使其成为一个私有变量。因此,我们需要遵循一个约定,所有在类或对象之中使用的变量,其命名应以下划线开头,其它所有非此格式的变量都是公开的,并且能被其它任何类或对象使用。 除了双下划线这点,Python并不会强制这样做。

继承一个类

面向对象的一个优点就是代码重用(Reuse)。重用的一种实现方式就是通过继承机制(Inheritance)。继承是在类之间实现类型(Type)与子类型(Subtype)的工具。
请看下面的例子

未命名文件

# base class
class SchoolManager:
    # 共有的属性 name  age
    def __init__(self,name,age):
        self.userName = name
        self.userAge = age
    def tellMe(self):
        print("Initialztion manaher:{},age:{}".format(self.userName,self.userAge))
# subclass
class Teacher(SchoolManager):
    # salary 子类私有属性
    def __init__(self,name,age,salary):
        SchoolManager.__init__(self,name,age)
        self.userSalary = salary
        print("Iniyialzation teacher,name:{},age:{}.salary:{}".format(self.userName,self.userAge,self.userSalary))
    def tellMe(self):
        # 这时候会调用一次基类的初始化方法
        SchoolManager.tellMe(self)
        print("{} salary is {}".format(self.userName,self.userAge))
# subclass
class Student(SchoolManager):
    # grade子类私有属性
    def __init__(self,name,age,grade):
        SchoolManager.__init__(self,name,age)
        self.userGrade = grade
        print("Initialzation student,name:{},age:{},grade:{}".format(self.userName,self.userAge,self.userGrade))
    def tellMe(self):
        # 这时候会调用一次基类的初始化方法
        SchoolManager.tellMe(self)
        print("{} grade is {}".format(self.userName,self.userGrade))


teacher = Teacher("mR.XXOO",18,45000)
student = Student("Tom",25,99)

print("\n")

member = [teacher,student]
for m in member:
    m.tellMe()
    print("\n")

输出结果

Iniyialzation teacher,name:mR.XXOO,age:18.salary:45000
Initialzation student,name:Tom,age:25,grade:99


Initialztion manaher:mR.XXOO,age:18
mR.XXOO salary is 18


Initialztion manaher:Tom,age:25
Tom grade is 99


Process finished with exit code 0

如上,我们对SchoolManager做出改变时,这种改变会反映到所有子类中,但是对TeacherStudent这两个子类中的一个做出改变时都不会影响到其它子类。另外,TeacherStudent可以被看做SchoolManager的对象加以引用。这被称为多态(Polymorphism)
我们重用父类中的代码,不需要在其它子类中重复这些代码。但是,当我们使用独立类型时,才可以重复使用这些代码。
当继承元组中有多个类时,称为多继承或多重继承,如class Teacher(SchoolManager,UserOperation):

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,599评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,581评论 18 399
  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 1,679评论 0 9
  • Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的...
    有一种再见叫青春阅读 577评论 0 3
  • 东南亚电商平台Lazada融资2.49亿美元http://tech.qq.com/a/20141201/06317...
    许卫栋阅读 361评论 0 1