美文网首页
跟我一起学Python(五)

跟我一起学Python(五)

作者: _花 | 来源:发表于2018-11-01 18:17 被阅读0次

类和实例

类的定义和实例化

面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板而实例是根据类创建出来的一个个具体的“对象”。
在Python中,定义类是通过class关键字:class后面紧接着是类名,即Student,类名通常是大写开头的单词,紧接着是(object),表示该类是从哪个类继承下来的。

class Student(object):
    pass

根据Student类创建出Student的实例,创建实例是通过类名+()实现的:

bart = Student()

可以在创建类的时候,通过定义一个特殊的init方法,把一些公共的属性写进去。

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score
   def print_score(self):  #类方法
        print('%s: %s' % (self.name, self.score))

创建实例时,参数必须与公共属性相对应(不传self),调用类方法时也不需要传self

bart = Student('Bart Simpson', 59)
bart.print_score()

也可以在实例上定义属性和属性方法

def set_age(self, age): # 定义一个函数作为实例方法
   self.age = age
from types import MethodType
bart .set_age = MethodType(set_age, bart ) # 给实例绑定一个方法
bar.gender = '男' #绑定属性

类的方法和普通函数没有什么区别,所以,你仍然可以用默认参数、可变参数、关键字参数和命名关键字参数。

私有变量

在属性名称前面加__,则该属性就是类的私有变量,只可以在类的内部被访问

  1. 当你看到一个下划线开头的实例变量名,如_name这样的是里外不是可以访问得到的,但按照约定俗成的规定,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。
  2. 双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:(但是不同版本的Python解释器可能会把__name改成不同的变量名,有可能换个解释器你用_Student__name就访问不到了。)

实例属性和类属性

给实例绑定属性的方法是通过实例变量,或者通过self变量:
如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:

class Student(object):
    name = 'Student'

当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。

类的三大特点

封装

面向对象编程的特点之一就是封装,尽量将可以封装的数据封装在类里面,也包括引用这些数据的函数。

class Student(object):

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

    def print_score(self):
        print('%s: %s' % (self.name, self.score))

继承

当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

class Animal(object):
    def run(self):
        print('Animal is running...')
class Dog(Animal):
    def eat(self):
        print('Eating meat...')
dog = Dog()
dog.run()

判断某个实例是否是某个类的实例

>>> isinstance(dog , Dog)
True
>>> isinstance(dog , Animal)
True

super() 函数是用于调用父类(超类)的一个方法。
super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。

多态

当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),这就叫多态。

class Dog(Animal):
    def run(self):
        print('Dog is running...')

上面给Dog子类也添加了run方法,这样子类Dog里的方法则会取代父类的;

获取对象信息

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
type()

print(type(dog))  #<class '__main__.Dog'>

判断基本数据类型可以直接写int,str
但如果要判断一个对象是否是函数怎么办?可以使用types模块中定义的常量:

>>> import types
>>> def fn():
...     pass
...
>>> type(fn)==types.FunctionType
True

isinstance()
isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。

>>> isinstance(dog , Dog)
True
>>> isinstance(dog , Animal)
True

并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是list或者tuple:

>>> isinstance([1, 2, 3], (list, tuple))
True

dir()
如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:
配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

hasattr(dog, 'run') # 有属性'run'吗?#不可以用 in 代替
True
>>> setattr(dog, 'y', 19) # 设置一个属性'y'
>>> hasattr(dog, 'y') # 有属性'y'吗?
True
>>> getattr(dog, 'y') # 获取属性'y' ,获取不存在的参数就会抛出错误
19
>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404

要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。

相关文章

网友评论

      本文标题:跟我一起学Python(五)

      本文链接:https://www.haomeiwen.com/subject/tqvxxqtx.html