Python语言学习:类和实例
小标 2019-01-17 来源 : 阅读 997 评论 0

摘要:本文主要向大家介绍了Python语言学习:类和实例,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

本文主要向大家介绍了Python语言学习:类和实例,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助。

类,在学习面向对象我们可以把类当成一种规范,这个思想就我个人的体会,感觉很重要,除了封装的功能外,类作为一种规范,我们自己可以定制的规范,从这个角度来看,在以后我们学习设计模式的时候,对设计模式的理解会很有帮助。其次,语言中类是抽象的模板,用来描述具有相同属性和方法的对象的集合,比如Animal类。而实例是根据类创建出来的一个个具体的“对象”,每个对象都拥有相同的方法,但各自的数据可能不同。

Python使用class关键字来定义类,其基本结构如下:

class 类名(父类列表):    pass

类名通常采用驼峰式命名方式,尽量让字面意思体现出类的作用。Python采用多继承机制,一个类可以同时继承多个父类(也叫基类、超类),继承的基类有先后顺序,写在类名后的圆括号里。继承的父类列表可以为空,此时的圆括号可以省略。但在Python3中,即使你采用类似classStudent:pass的方法没有显式继承任何父类的定义了一个类,它也默认继承object类。因为,object是Python3中所有类的基类。

下面是一个学生类:

class Student:
   classroom = '101'
   address = 'beijing'

   def __init__(self, name, age):        self.name = name        self.age = age    def print_age(self):
       print('%s: %s' % (self.name, self.age))

可以通过调用类的实例化方法(有的语言中也叫初始化方法或构造函数)来创建一个类的实例。默认情况下,使用类似obj=Student()的方式就可以生成一个类的实例。但是,通常每个类的实例都会有自己的实例变量,例如这里的name和age,为了在实例化的时候体现实例的不同,Python提供了一个def__init__(self):的实例化机制。任何一个类中,名字为__init__的方法就是类的实例化方法,具有__init__方法的类在实例化的时候,会自动调用该方法,并传递对应的参数。比如:

class Student:
li = Student("李四", 24)
zhang = Student("张三", 23)

实例变量和类变量

实例变量:

实例变量指的是实例本身拥有的变量。每个实例的变量在内存中都不一样。Student类中__init__方法里的name和age就是两个实例变量。通过实例名加圆点的方式调用实例变量。

我们打印下面四个变量,可以看到每个实例的变量名虽然一样,但他们保存的值却是各自独立的:

print(li.name)print(li.age)print(zhang.name)print(zhang.age)------------------------李四24张三23

类变量:

定义在类中,方法之外的变量,称作类变量。类变量是所有实例公有的变量,每一个实例都可以访问、修改类变量。在Student类中,classroom和address两个变量就是类变量。可以通过类名或者实例名加圆点的方式访问类变量,比如:

Student.classroomStudent.addressli.classroomzhang.address

在使用实例变量和类变量的时候一定要注意,使用类似zhang.name访问变量的时候,实例会先在自己的实例变量列表里查找是否有这个实例变量,如果没有,那么它就会去类变量列表里找,如果还没有,弹出异常。

Python动态语言的特点,让我们可以随时给实例添加新的实例变量,给类添加新的类变量和方法。因此,在使用li.classroom = '102'的时候,要么是给已有的实例变量classroom重新赋值,要么就是新建一个li专属的实例变量classroom并赋值为‘102’。看下面的例子

>>> class Student:              # 类的定义体
   classroom = '101'           # 类变量
   address = 'beijing'

   def __init__(self, name, age):        self.name = name        self.age = age    def print_age(self):
       print('%s: %s' % (self.name, self.age))>>> li = Student("李四", 24)        # 创建一个实例>>> zhang = Student("张三", 23)     # 创建第二个实例>>> li.classroom # li本身没有classroom实例变量,所以去寻找类变量,它找到了!'101'>>> zhang.classroom # 与li同理'101'>>> Student.classroom   # 通过类名访问类变量'101'>>> li.classroom = '102'    # 关键的一步!实际是为li创建了独有的实例变量,只不过名字和类变量一样,都叫做classroom。>>> li.classroom    # 再次访问的时候,访问到的是li自己的实例变量classroom'102'>>> zhang.classroom # zhang没有实例变量classroom,依然访问类变量classroom'101'>>> Student.classroom   # 保持不变'101'>>> del li.classroom    # 删除了li的实例变量classroom>>> li.classroom        # 一切恢复了原样'101'>>> zhang.classroom'101'>>> Student.classroom'101'

类的方法:

Python的类中包含实例方法、静态方法和类方法三种方法。这些方法无论是在代码编排中还是内存中都归属于类,区别在于传入的参数和调用方式不同。在类的内部,使用def关键字来定义一个方法。

实例方法

类的实例方法由实例调用,至少包含一个self参数,且为第一个参数。执行实例方法时,会自动将调用该方法的实例赋值给self。self代表的是类的实例,而非类本身。self不是关键字,而是Python约定成俗的命名,你完全可以取别的名字,但不建议这么做。

例如,我们前面Student类中的print_age()就是实例方法:

def print_age(self):
       print('%s: %s' % (self.name, self.age))# --------------------------# 调用方法li.print_age()
zhang.print_age()

静态方法

静态方法由类调用,无默认参数。将实例方法参数中的self去掉,然后在方法定义上方加上@staticmethod,就成为静态方法。它属于类,和实例无关。建议只使用类名.静态方法的调用方式。(虽然也可以使用实例名.静态方法的方式调用)

class Foo:    @staticmethod
   def static_method():
       pass#调用方法Foo.static_method()

类方法

类方法由类调用,采用@classmethod装饰,至少传入一个cls(代指类本身,类似self)参数。执行类方法时,自动将调用该方法的类赋值给cls。建议只使用类名.类方法的调用方式。(虽然也可以使用实例名.类方法的方式调用)

class Foo:    @classmethod
   def class_method(cls):
       passFoo.class_method()

看一个综合例子:

class Foo:

   def __init__(self, name):
       self.name = name

   def ord_func(self):
       """定义实例方法,至少有一个self参数 """
       print('实例方法')    @classmethod
   def class_func(cls):
       """ 定义类方法,至少有一个cls参数 """
       print('类方法')    @staticmethod
   def static_func():
       """ 定义静态方法 ,无默认参数"""
       print('静态方法')
# 调用实例方法f = Foo("Jack")
f.ord_func()
Foo.ord_func(f) # 请注意这种调用方式,虽然可行,但建议不要这么做!# 调用类方法Foo.class_func()
f.class_func()  # 请注意这种调用方式,虽然可行,但建议不要这么做!# 调用静态方法Foo.static_func()
f.static_func() # 请注意这种调用方式,虽然可行,但建议不要这么做!

类、类的方法、类变量、类的实例和实例变量在内存中是如何保存的?

类、类的所有方法以及类变量在内存中只有一份,所有的实例共享它们。而每一个实例都在内存中独立的保存自己和自己的实例变量。

创建实例时,实例中除了封装诸如name和age的实例变量之外,还会保存一个类对象指针,该值指向实例所属的类的地址。因此,实例可以寻找到自己的类,并进行相关调用,而类无法寻找到自己的某个实例。

Python 类的继承

在ptyhon中类一个类是可以同时继承多个类,语法:

class 类名(父类1,父类2,...)

类体

Python类继承之深度优先

python 支持多继承,但对与经典类和新式类来说,多继承查找的顺序是不一样的。

经典类:

class P1:
    def foo(self):          
        print 'p1-foo' class P2 :
    def foo(self):
        print 'p2-foo'

    def bar(self):
        print 'p2-bar' class C1 (P1,P2):
    pass  class C2 (P1,P2):
    def bar(self):
        print 'C2-bar'   class D(C1,C2):
    pass

实例d调用foo()时,搜索顺序是 D => C1 => P1

实例d调用bar()时,搜索顺序是 D => C1 => P1 => P2

换句话说,经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,如果没有则继续向上查找,直到在P1中找到该方法,查找结束。

Python类继承之广度优先

新式类:

class P1(object):
    def foo(self):          
        print 'p1-foo' class P2(object):
    def foo(self):
        print 'p2-foo'

    def bar(self):
        print 'p2-bar' class C1 (P1,P2):
    pass  class C2 (P1,P2):
    def bar(self):
        print 'C2-bar'   class D(C1,C2):
    pass

实例d调用foo()时,搜索顺序是 D => C1 => C2 => P1
实例d调用bar()时,搜索顺序是 D => C1 => C2
可以看出,新式类的搜索方式是采用“广度优先”的方式去查找属性。

本文由职坐标整理并发布,希望对同学们学习Python有所帮助,更多内容请关注职坐标编程语言Python频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程