类,类对象和属性,类实例化
__init__方法(构造方法),self
类变量和实例变量

面向过程与面向对象


  1. 面向过程
    • 分析出解决问题所需要的的步骤
    • 用函数将这些步骤一步步实现
    • 依次调用函数即可
  2. 面向对象
    • 把构成问题事物分解成各个对象
    • 建立对象的目的不是为了完成某一个步骤,而是为了描述某个事物在整个解决问题步骤中的行为

认识面向对象


    • 是一类事物的共同特征的集合
    • 属性方法的集合
  1. 对象
    • 是类的一个实体
  2. 属性
    • 对象状态的抽象,用数据结构来描述
  3. 操作
    • 对象行为的抽象,用操作名和实现该操作的方法来描述

面向对象三要素


  1. 封装
  2. 继承
  3. 多态

python的类


  • 类的定义:class关键字,大驼峰命名,类定义完成后就产生一个类对象
  • 类对象及类属性
    • 类对象:类的定义执行后就会生成一个类对象
    • 类属性:类定义中的变量和类中定义的方法
  • 实例化:创建一个类的对象的实例

__init__方法

  • 对实例进行初始化
  • 初始化方法,也称构造方法,类似 java 构造方法,用来初始化成员属性和成员方法,即创建对象后,就调用对象的属性和方法。进一步理解可参看魔术方法章节中__init__本质
  • 可以不定义,如果没定义会在实例化后隐式调用
  • 不能有返回值,也就是说只能是 return None
class MyClass:
    def __init__(self):
        print('init')

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

self

  • 当前实例本身
  • 可以换名字,只是习惯用self表示当前实例本身
class Person():
    """A example of class"""
    adress = 'shanghai' # 类变量,类属性
    def __init__(self,name,age): # self 当前实例本身
        self.name = name # self.name 实例的属性
        self.age = age
        print(self,id(self))
    def show_age(self): # 类属性,类方法
        print(self.age)
        print(id(self))

# 一般情况下不直接使用类调用,一般先实例化
print(type(Person),type(int),type(str))
print(Person.adress)
print(Person.__doc__)
print(Person.__name__)
print(Person.show_age)
# Person.show_age() # 报错,没有self实例

print('~'*100)

# 实例化
j = Person('jerry',18)
t = Person('tom',20)

print('*'*100)

print(j,t) # 不同的实例对象
print(j.name,t.age)
Person.show_age(j) # 不报错,给了实例j
print(j.show_age,t.show_age) # bound method 将j实例与self绑定
j.show_age()
t.show_age()

print(j.adress,t.adress)
# 实例变量是每一个实例自己的变量,是自己独有的;类变量是类的变量,是类的所有实例共享的属性和方法
Person.adress = 'beijing'
print(j.adress,t.adress)
--------------------------------------------------------------------------------------
<class 'type'> <class 'type'> <class 'type'>
shanghai
A example of class
Person
<function Person.show_age at 0x0000022837181268>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<__main__.Person object at 0x000002283718CE48> 2371746319944
<__main__.Person object at 0x000002283718CDD8> 2371746319832
****************************************************************************************
<__main__.Person object at 0x000002283718CE48> <__main__.Person object at 0x000002283718CDD8>
jerry 20
18
2371746319944
<bound method Person.show_age of <__main__.Person object at 0x000002283718CE48>> <bound method Person.show_age of <__main__.Person object at 0x000002283718CDD8>>
18
2371746319944
20
2371746319832
shanghai shanghai
beijing beijing

类变量和实例变量


  • __name__: 对象名
  • __class__:对象的类型,相当于 type(对象)
  • __dict__:对象的属性的字典
  • __qualname:类的限定名
# 仍利用上面的例子来认识几个特殊属性
print(Person.__name__,Person.__class__,type(Person),type(Person).__name__,Person.__class__.__name__)
print(Person.__dict__)
# print(j.__name__) # 报错,实例没有该属性
print('~'*100)
print(j.__class__)
print(j.__dict__,t.__dict__)
-----------------------------------
Person <class 'type'> <class 'type'> type type
{'__module__': '__main__', '__doc__': 'A example of class', 'adress': 'beijing', '__init__': <function Person.__init__ at 0x00000228371237B8>, 'show_age': <function Person.show_age at 0x000002283714AD90>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<class '__main__.Person'>
{'name': 'jerry', 'age': 18} {'name': 'tom', 'age': 20}

深入理解类变量和实例变量

class Person:    
    age = 3    
    height = 170    
    def  __init__(self, name, age= 18):
        self.name = name
        self.age = age
    
tom = Person('Tom') 
jerry = Person('Jerry', 20)
Person.age = 30
print(1, Person.age, tom.age, jerry.age) # 30 18 20
print(2, Person.height, tom.height, jerry.height) # 170 170 170
jerry.height = 175
print(jerry.__dict__)
print(3, Person.height, tom.height, jerry.height) # 170 170 175
tom.height += 10
print(tom.__dict__)
print(4, Person.height, tom.height, jerry.height) # 170 180 175
Person.height += 15
print(5, Person.height, tom.height, jerry.height) # 185 180 175
Person.weight = 70
print(6, Person.weight, tom.weight, jerry.weight) # 70 70 70
print(Person.__dict__)
print(7, tom.__dict__['height']) # 180
# print(8, tom.__dict__['weight']) # 报错,tom的dict中没有weight属性,不遵循.的查找顺序
-----------------------------------------------------------------------
1 30 18 20
2 170 170 170
{'name': 'Jerry', 'age': 20, 'height': 175}
3 170 170 175
{'name': 'Tom', 'age': 18, 'height': 180}
4 170 180 175
5 185 180 175
6 70 70 70
{'__module__': '__main__', 'age': 30, 'height': 185, '__init__': <function Person.__init__ at 0x0000022837181C80>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None, 'weight': 70}
7 180

关于类变量和实例变量相关结论

  1. 类变量是属于类的变量,这个类的所有实例可以共享这个变量
  2. 实例变量是实例自己的,类不能访问到
  3. 对象(实例或类)可以动态的给自己增加一个属性(赋值即定义一个新属性)
  4. 实例.__dict__[变量名]实例.变量名都可以访问到实例自己的属性(注意这两种访问是有本质区别的)
  5. 实例属性的查找顺序 (实例使用.点号来访问属性),会先找自己的__dict__,如果没有,然后通过属性__class__找到自己的类,再去类的__dict__中找
  6. 注意:如果实例使用__dict__[变量名]访问变量,将不会按照上面的查找顺序找变量了,这是指明使用字典的 key 查找,不是属性查找

参考


  • magedu