python基础-类

类:

  构造函数:

  数据封装:

  访问限制:

  继承和多态:

  获取对象信息:

    判断类型type()

    判断class的类型: isinstance()

    属性和方法:dir()

    提取方法:getattr()

--------------------------------------------------------------------------------------------------------------------------------------------

一、类:

  类是抽象的模板,而实例是根据类创建出来的一个个具体的“对象”,每个象都拥有相同的方法,但各自的据可能不同。

  如果没有合适的继承类,就使用object类:

>>>class Student(object):
...    pass
>>> bart = Student()
>>> bart
<__main__.Student object at 0x10a67a590>
>>> Student
<class '__main__.Student'>

  自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性:

>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'

  构造函数:__init__:

class Student(object):

    def __init__(self,name,score):
        self.name=name
        self.score=score
#在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。

   有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数:

>>> bart = Student('Bart Simpson', 59)
>>> bart.name
'Bart Simpson'
>>> bart.score
59

  和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self,并且,调用时,不用传递该参数

  数据封装:定义方法

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)
>>> bart.get_grade()
'C'

二、访问限制:如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

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)

    如果要获取和设置内部变量,可以增加get,set方法,以便检查值是否合法

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

    def set_name(self,name):
        self.__name = name

    def set_score(self,score):
        if 0<= score <= 100:
            self.score = score
        else:
            raise ValueError('Bad score')    #抛出异常.

    变量名类似__xxx__的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用__name____score__这样的变量名。

    双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:

>>> bart._Student__name
'Bart Simpson'

    注意:但是建议不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名。

三、继承和多态:从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)

    继承有什么好处?最大的好处是子类获得了父类的全部功能,也可以对子类增加一些方法。

    当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,就是:多态

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

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

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

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

    当定义一个class的时候,就定义了一种数据类型,判断一个变量是否是某个类型可以用isinstance()判断:

>>>a = list() # a是list类型
>>>b = Animal() # b是Animal类型
>>>c = Dog() # c是Dog类型
>>> isinstance(a, list)
True
>>> isinstance(b, Animal)
True
>>> isinstance(c, Dog)
True

    在继承中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类,但是,反过来不行:

>>> b = Animal()
>>> isinstance(b, Dog)
False

    当调用一个以父类定义的函数时,可以传入子类实例,并且调用的是子类实例的方法。这就是多态,也是“开闭原则”

    对扩展开放:允许继承父类的子类;

    对修改封闭:不需要修改依赖 父类类型 定义的函数。

四、获取对象信息:对象是什么类型、有哪些方法?

  判断类型:type(),     type()函数返回type类型。

>>> type(123)
<type 'int'>
>>> type('str')
<type 'str'>
>>> type(None)
<type 'NoneType'>

      每种type类型都定义好了常量,放在types模块里

>>> import types
>>> type('abc')==types.StringType
True
>>> type(u'abc')==types.UnicodeType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType
True

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

>>> a = Animal()
>>> d = Dog()
>>> h = Husky()
>>> isinstance(h, Husky)
True

    判断一个变量是否是某些类型中的一种:

>>> isinstance('a', (str, unicode))
True
>>> isinstance(u'a', (str, unicode))
True

    strunicode都是从basestring继承下来的,so:

>>> isinstance(u'a', basestring)
True

  属性和方法:使用dir()函数,它返回一个包含字符串的list

>>> dir('ABC')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

    类似__xxx__属性方法在Python中都是有特殊用途,

    比如,__len__方法返回长度,

    调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法:

>>> len('ABC')
3
>>> 'ABC'.__len__()
3

    配合getattr()setattr()以及hasattr(),我们可以直接操作一个对象的状态.异常AttributeError

>>> hasattr(obj, 'x') # 有属性'x'吗?
True
>>> obj.x
9
>>> hasattr(obj, 'y') # 有属性'y'吗?
False
>>> setattr(obj, 'y', 19) # 设置一个属性'y'
>>> hasattr(obj, 'y') # 有属性'y'吗?
True
>>> getattr(obj, 'y') # 获取属性'y'
19
>>> obj.y # 获取属性'y'
19
>>> getattr(obj, 'z') # 获取属性'z'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'MyObject' object has no attribute 'z'

    传入一个default参数,如果属性不存在,就返回默认值:

>>> getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
404

    获得对象的方法并赋值:

>>> hasattr(obj, 'power') # 有属性'power'吗?
True
>>> getattr(obj, 'power') # 获取属性'power'
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81
原文地址:https://www.cnblogs.com/xccnblogs/p/4915556.html