类 1 新式类和经典类 2 类的定义 3 类和对象 4 继承 5 组合和派生 6 接口和抽象类 7 super的写法 8 多态 9 封装 10 使用property 11 静态方法和类方法

  查看父类信息的方法

类名.__bases__

  在Python3中默认是新式类, 不管写不写继承

  Python2中默认是经典类, 不继承任何, 父类为空

>>> class A:
...     pass
...
>>> A.__bases__
()

  如果要定义新式类, 需要手动写入继承object

>>> class A:
...     pass
...
>>> A.__bases__
()

2 类的定义

  定义格式为:

class 类名(父类列表):
    类体

  其中类名首字母一般大写

  父类可以有多个, Python支持多继承

3 类和对象

  类体中可以直接写入变量, 这是类的属性, 类和对象都可以调用该属性

  类体中可以定义函数, 此函数第一个参数始终是self, 用于给对象绑定方法

  其中有个特殊函数是 __init__(self, 参数列表)

    该函数在生成对象的时候会调用该方法, 且参数列表需要一一对应

  查看类的名称空间

类名.__dict__

  基本的定义情况

class Student:
    country = 'China'

    def __init__(self, ID, NAME, SEX, PROVINCE):
        self.id = ID
        self.name = NAME
        self.sex = SEX
        self.province = PROVINCE

    def getScore(self):
        print(self.score)

    def setScore(self, score):
        self.score = score

s1 = Student('000', 'weihuchao', 'male', 'chongqing')
print( s1.name )
s1.setScore(100)
s1.getScore()

Student.getScore(s1)

print( id(Student.getScore ) )
print( id(s1.getScore ) )

  类的作用

    1) 生成对象

对象名 = 类名(参数列表)

    2) 属性引用

类名.类属性
#或者
类名.函数(类的对象, 参数列表)

  对象的作用

    调用属性和绑定方法

    其中类的函数和对象的方法是不一样的, 尽管事实上实现的功能一致

    对象会先找自己空间是否有属性, 没有就会调用类中的

    如果实赋值语句, 则会绑定一个新的属性

    解除绑定用del

4 继承

  继承会继承父类所有公开的属性和方法

  Python支持多继承

  Python3的多继承查找是c3算法, 可以使用__mro__查看顺序

类名.__mro__

  python2中经典类的多继承查找是 深度优先算法

5 组合和派生

  组合是在绑定属性的时候使用别的类的对象

  派生就是继承之后绑定新的属性和方法

6 接口和抽象类

  接口是光定义函数不实现

  但是无法限制子类继承的时候必须实现那些方法

  要实现限制子类必须实现那些方法, 可以定义一个抽象类

  抽象类是导入abc模块来实现

    需要继承内写入 metaclass=abc.ABCMeta

    给方法加入装饰器 abc.abstractmethod

  具体实现如下

import abc

class Animal(metaclass=abc.ABCMeta):
    tag='123123123123123'
    @abc.abstractmethod
    def run(self):
        pass
    @abc.abstractmethod
    def speak(self):
        pass

class People(Animal):
    def run(self):
        pass

    def speak(self):
        pass

peo1=People()
print(peo1.tag)

7 super的写法

  在继承的时候, 可能会调用父类的方法, 但是由于python可以多继承, 所以直接指定父类来调用函数容易出现多种问题

  所以在调用父类方法的时候使用super方法

  格式如下

super(当前类名, self).__init__(参数列表)

  具体实例为

class People:
    def __init__(self,name,sex,age):
        self.name=name
        self.age=age
        self.sex=sex
    def walk(self):
        print('父类的walk()')


class Chinese(People):
    country='China'
    def __init__(self,name,sex,age,language='Chinese'):
        super(Chinese,self).__init__(name,sex,age)
        self.language=language
    def walk(self):
        super(Chinese, self).walk()
        print('子类的walk()')

8 多态

  父类引用指向子类对象

  具体就是 将子类的对象当做参数传入, 传入给他的父类对象, 用父类对象去调用方法, 实际上是调用的子类的方法而不是父类的方法

  具体实例如下

class Animal:
    def run(self):
         print('动物正在走')   

class People(Animal):
    def run(self):
        print('人正在走')

class Pig(Animal):
    def run(self):
        print('pig is walking')

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

def func(obj):
    obj.run()

9 封装

  在类中, 可以通过将名字在前面加上__(双下划线)来标识这是私有变量

  在类中, 可以通过 __属性名 来调用该属性  

  在类外, 无法通过 __属性名 就找到该属性

  事实上, 改变了在定义后该变量名字会变成 _类名__属性名 

  但是不建议通过这样的方法来调用该参数

  因而正常情况下, 会编写一个调用该属性的方法当做对外的接口

  具体实例如下

class Student:
    def __init__(self, ID, NAME):
        self.__id = ID
        self.__name = NAME
        
    def getId(self):
        print(self.__id)

    def setId(self, ID):
        self.__id = ID
    
    def getName(self):
        print(self.__name)

    def setName(self, NAME):
        self.__name = NAME

10 使用property

  有的类里面可以通过函数来返回相关的属性值, 比如圆类中, 可以计算周长和面积

  但是这样的用户体验并不好, 我们希望直接通过 调用属性的形式来访问 这个样的属性值, 此时就可以是用装饰器property

  @property装饰器下的函数名, 可以通过 类名.函数名 直接获得该返回值

  具体实现代码如下

import math
class Circle:
    def __init__(self,radius):
        self.radius=radius

    @property
    def area(self):
        return math.pi * self.radius**2

    @property
    def perimeter(self):
        return 2*math.pi*self.radius

c=Circle(7)
print( c.area )
print( c.perimeter )

  @property只是获取属性, 还可以通过更多的装饰器来形成类似的 设置属性, 删除属性等

  设置属性的装饰器是 @函数名.setter

  删除属性的装饰器是 @函数名.deleter

  获得属性的装饰器是 @函数名.getter (这个的存在就覆盖了@property)

11 静态方法和类方法

  静态方法是使用 装饰器staticmethod来形成的函数

  该函数的特点是不需要写入self, 后面的参数列表是正常的参数列表, 而且调用的时候需要一一对应

  因而该函数也不会绑定给对象, 而是属于类的属性函数

  具体情形如下

class Foo:
    @staticmethod
    def spam(x,y,z):
        print(x,y,z)

print(Foo.spam)
print(Foo().spam)
# <function Foo.spam at 0x0000000000B12620>
# <function Foo.spam at 0x0000000000B12620>

  类方法是使用装饰器classmethod

  类方法就是将方法绑定给类

  类方法第一个参数始终是cls, 代表调用它这个函数的对象的类传入给cls

  具体使用如下

class Foo:
    @classmethod
    def test(cls, x, y):
        print(cls, x, y)

Foo.test(1,2)
Foo().test(1,2)
# <class '__main__.Foo'> 1 2
# <class '__main__.Foo'> 1 2

  静态方法和类方法可以相互搭配, 形成很好的效果

import time
class Date:
    def __init__(self,year,month,day):
        self.year=year
        self.month=month
        self.day=day
    @classmethod
    def now(cls):
        t=time.localtime()
        obj=cls(t.tm_year,t.tm_mon,t.tm_mday)
        return obj
    @classmethod
    def tomorrow(cls):
        t=time.localtime(time.time()+86400)
        return cls(t.tm_year,t.tm_mon,t.tm_mday)

class EuroDate(Date):
    def __str__(self):
        return '年:%s,月:%s,日:%s' %(self.year,self.month,self.day)

print( EuroDate.now() )
# 年:2017,月:4,日:21