面向对象-类

面向对象是一种认识世界,分析世界的方法论,将万事万物抽象为类

 

类class

类是抽象的概念,是万事万物的抽象,是一类事物的共同特征集合

用计算机语言来描述类,就是属性和方法的集合

 

对象instance,object

对象是类的具象,是一个实体

一切皆对象

对象是数据和操作的封装

对象是独立的,但是对象之间可以相互作用

 

面向对象三要素

1.封装

  • 组装,将数据和操作组装到一起
  • 隐藏数据,对外只暴露一些接口,通过接口访问对象

2.继承

  • 多复用,继承来的就不用自己写
  • 多继承少修改,ocp使用继承来改变,来体现个性

3.多态

  • 面向对象编程最灵活的地方,动态绑定

 

人类就是封装;

热泪继承自动物类,孩子继承父母特征,分为单一继承,多继承,多态,继承自动物类的人类,猫类的操作吃不同

 

python的类定义

class ClassName:
    语句
  • 必须使用class关键字
  • 类名必须用大驼峰命名
  • 类定义完成后,就产生了一个类对象,绑定到了标识符ClassName上

 

示例:

class MyClass:
    """A example class"""
    x = 'abc' #类属性


    def foo(self): #类属性foo,也是方法
        return "hello world"

print(MyClass.x)
print(MyClass.foo)
print(MyClass.__doc__)

输出为:

abc
<function MyClass.foo at 0x000002091C9F3268>
A example class

 

类对象及类属性

  • 类对象,类的定义就会产生一个类对象
  • 类的属性,类定义中的变量和类中定义的方法都是类的属性
  • 类变量,上例中x是类MyClass的变量

MyClass中,x和foo都是泪的属性,__doc__也是类的属性

foo方法是类的属性,如同人类的方法,但是每一个具体的人才会吃东西,也就是说是人的实例才能调用的方法

foo是方法对象method,不是普通的函数对象function了,它一般要求至少有一个参数,第一个参数可以是self,这个参数位置留给self

self指当前历史本身

 

实例化

a = MyClass() #实例化

使用上面语法,在类对象名称后面加上一个括号,就调用类的实例化方法,完成实例化

实例化就真正的创建了一个该类的对象(实例)

示例:

tom  = Person()
jerry = Person()

tom和jerry都是Person类的实例,通过实例化生成2个实例

每次实例化后获得的实例,是不同的实例,即使是使用同样的参数实例化,也得不到一样的对象

python类实例化后,会自动调用__init__方法,这个方法第一个参数必须留给self自己

 

__init__方法

MyClass()实际上调用的是__init__(self)方法,可以不定义,如果没有定义会在实例化后隐式调用

__init__作用是对实例进行初始化

__init__()方法不能有返回值,也就是只能return None

示例:

class MyClass:
    def __init__(self):
        print('init')


print(MyClass)  # 不会调用
print(MyClass())  # 调用__init__
a = MyClass()  # 调用__init__

输出为:

<class '__main__.MyClass'>
init
<__main__.MyClass object at 0x000001F030782978>
init

 

初始化函数可以多个参数,第一个参数位置必须是self

示例:

class Person:
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def showage(self):
        print('{} is {}'.format(self.name,self.age))
        

tom = Person('tom', 18)
jerry = Person('jerry', 20)
print(tom.name, jerry.name)
jerry.age += 1
print(jerry.age)
jerry.showage()

输出为:

tom jerry
21
jerry is 21

 

实例对象instance

类实例化后一定会获得一个对象,就是实例对象

上例中tom和jerry就会Person类的实例

__init__方法的第一参数self就是指代某一个实例

类实例化后,得到一个实例对象,会绑定方法,调用方法时会采用jerry.showage()方式

python会把方法的调用者作为第一参数self的实参传入

self.name就是jerry对象的name,name是保存在jerry对象上,而不是Person类上,称为实例变量

 

self

示例:

class MyClass:
    def __init__(self):
        print('self in init = {}'.format(id(self)))


c = MyClass()  # 会调用__init__
print('c = {}'.format(id(c)))

输出为:

self in init = 1992925063824
c = 1992925063824

上例说明,self就是调用者,就是c对应的实例对象

self这个名字只是一个惯例,可可以修改,但是不要修改,会影响代码可读性

 

实例变量和类变量

class Person:
    age = 3

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


tom = Person('tom')
jerry = Person('jerry')

print(tom.name, tom.age)
print(jerry.name, jerry.age)
print(Person.age)
Person.age = 30
print(Person.age, tom.age, jerry.age)

输出为

tom 3
jerry 3
3
30 30 30

实例变量是每一个实例自己的变量,是自己独有的。类变量是类的变量,是类的所有实例共享的属性和方法

 

 

python中每一种对象都拥有不同的属性,函数,类都是对象,类的实例也是对象

示例:

class Person:
    age = 3

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


print('-----class-----')
print(Person.__class__)
print(sorted(Person.__dict__.items()),end='\n\n') #属性字典

tom = Person('tom')
print('------instance tom------')
print(tom.__class__)
print(sorted(tom.__dict__.items()),end='\n\n')

print('------tom class------')
print(tom.__class__.__name__)
print(sorted(tom.__class__.__dict__.items()),end='\n\n')

输出为

-----class-----
<class 'type'>
[('__dict__', <attribute '__dict__' of 'Person' objects>), ('__doc__', None), ('__init__', <function Person.__init__ at 0x000001D47E7A3268>),
('__module__', '__main__'), ('__weakref__', <attribute '__weakref__' of 'Person' objects>), ('age', 3)] ------instance tom------ <class '__main__.Person'> [('name', 'tom')] ------tom class------ Person [('__dict__', <attribute '__dict__' of 'Person' objects>), ('__doc__', None), ('__init__', <function Person.__init__ at 0x000001D47E7A3268>),
('__module__', '__main__'), ('__weakref__', <attribute '__weakref__' of 'Person' objects>), ('age', 3)]

类属性保存在类的__dict__中,实例属性保存在实例的__dict__中,如果从实例访问类的属性,就需要借助__class__找到所属的类

 

示例:

class Person:
    age = 3
    height = 170

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


tom = Person('tom')
jerry = Person('jerry')

Person.age = 30
print(Person.age, tom.age, jerry.age)
print(Person.height, tom.height, jerry.height)
jerry.height = 175
print(Person.height, tom.height, jerry.height)
tom.height += 10
print(Person.height, tom.height, jerry.height)
Person.height += 20
print(Person.height, tom.height, jerry.height)
Person.weight = 70
print(Person.weight, tom.weight, jerry.weight)

print(tom.__dict__['height'])
print(tom.__dict__['weight'])

输出为:

30 30 30
170 170 170
170 170 175
170 180 175
190 180 175
70 70 70
180
Traceback (most recent call last):
  File "E:/PycharmProjects/untitled/test/a.py", line 33, in <module>
    print(tom.__dict__['weight'])
KeyError: 'weight'

类属性类方法是类的,也是这个类所有实例的,其实例都可以访问到,是实例的,就是这个实例自己的,通过类访问不到,类变量是属于类的变量,这个类的所有实例可以共享这个变量

对象(实例或类)可以动态的给自己增加一个属性,实例的同名变量会隐藏掉类变量,或者说是覆盖了这个类变量

实例属性的查找顺序

实例会先找自己的__dict__,如果没有,通过属性__class__找到自己的类,再去类的__dict__中找

 

装饰一个类

为一个类通过装饰,增加一些类属性,例如给一个类增加NAME属性并提供属性值

def add_name(name):
    def wrapper(cls):
        cls.NAME = name
        return cls
    return wrapper


@add_name('tom')
class Person:
    AGE = 3


print(Person.NAME)

本质上是为类对象动态增加了一个属性,而Person这个标识符指向这个类对象

posted @ 2018-09-19 23:17  rivendare  阅读(187)  评论(0编辑  收藏  举报