类与对象

一,类

  个人理解,类是以函数为基础,通过__init__(self),把一些重复使用的参数加以打包于一起,以达到简化工程的目的。(可以最后看这句话)

 1 1 def CarInfo(type,price):
 2  2     print "the car's type %s,price:%d"%(type,price)
 3  3 
 4  4 
 5  5 CarInfo('passat',250000)
 6  6 CarInfo('ford',280000)
 7  7 
 8  8 
 9  9 
10 10 
11 11 class Car:   #定义了一个类
12 12     def __init__(self,type,price):   #在类中编写了一个对象
13 13         self.type = type
14 14         self.price = price
15 15 
16 16     def printCarInfo(self):
17 17         print "the car's Info in class:type %s,price:%d"%(self.type,self.price)
18 18 
19 19 carOne = Car('passat',250000)  #创建了一个对象或者说实例化了一个对象
20 20 carTwo = Car('ford',250000)     
21 21 carOne.printCarInfo()  #通过对象调用其中一个方法
22 22 carTwo.printCarInfo()
23 
24  fnction_class_CompareCode

  运行代码可知,两者结果相同,我想说的是,函数都可以转化为类。下面这个例子是类利用比较好的例子。

 1 class UserInfo:
 2 
 3     def __init__(self):
 4         self.name = None
 5 
 6     def info(self):
 7         print('当前用户名称:%s' %(self.name,))
 8 
 9     def account(self):
10         print('当前用户%s的账单是:....' %(self.name,))
11 
12     def shopping(self):
13         print('%s购买了一个人形抱枕' %(self.name,))
14 
15     def login(self):
16         user = input('请输入用户名:')
17         pwd = input('请输入密码:')
18         if pwd == 'sb':
19             self.name = user
20             while True:
21                 print("""
22                     1. 查看用户信息
23                     2. 查看用户账单
24                     3. 购买抱枕
25                 """)
26                 num = int(input('请输入选择的序号:'))
27                 if num == 1:
28                     self.info()
29                 elif num ==2:
30                     self.account()
31                 elif num == 3:
32                     self.shopping()
33                 else:
34                     print('序号不存在,请重新输入')
35         else:
36             print('登录失败')
37 
38 obj = UserInfo()
39 obj.login()

 二,类的三大特性

  1. 封装,就是将函数的参数封装到self中

     

    self 是一个形式参数,当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1

                                  当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2

    所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。

     

    例子,游戏场景,分别:

    • 草丛战斗,消耗200战斗力
    • 自我修炼,增长100战斗力
    • 多人游戏,消耗500战斗力
    •  1 # -*- coding:utf-8 -*-
       2 
       3 # #####################  定义实现功能的类  #####################
       4 
       5 class Person:
       6 
       7     def __init__(self, na, gen, age, fig):
       8         self.name = na
       9         self.gender = gen
      10         self.age = age
      11         self.fight =fig
      12 
      13     def grassland(self):
      14         """注释:草丛战斗,消耗200战斗力"""
      15 
      16         self.fight = self.fight - 200
      17 
      18     def practice(self):
      19         """注释:自我修炼,增长100战斗力"""
      20         
      21         self.fight = self.fight + 200
      22 
      23     def incest(self):
      24         """注释:多人游戏,消耗500战斗力"""
      25         
      26         self.fight = self.fight - 500
      27 
      28     def detail(self):
      29         """注释:当前对象的详细情况"""
      30 
      31         temp = "姓名:%s ; 性别:%s ; 年龄:%s ; 战斗力:%s"  % (self.name, self.gender, self.age, self.fight)
      32         print temp
      33 
      34         
      35 # #####################  开始游戏  #####################
      36 
      37 cang = Person('苍井井', '', 18, 1000)    # 创建苍井井角色
      38 dong = Person('东尼木木', '', 20, 1800)  # 创建东尼木木角色
      39 bo = Person('波多多', '', 19, 2500)      # 创建波多多角色
      40 
      41 cang.incest() #苍井空参加一次多人游戏
      42 dong.practice()#东尼木木自我修炼了一次
      43 bo.grassland() #波多多参加一次草丛战斗
      44 
      45 
      46 #输出当前所有人的详细情况
      47 cang.detail()
      48 dong.detail()
      49 bo.detail()
      50 
      51 
      52 cang.incest() #苍井空又参加一次多人游戏
      53 dong.incest() #东尼木木也参加了一个多人游戏
      54 bo.practice() #波多多自我修炼了一次
      55 
      56 #输出当前所有人的详细情况
      57 cang.detail()
      58 dong.detail()
      59 bo.detail()
      60 游戏人生
      游戏人生

       

  2. 继承,父类中的函数可以被子类调用

     1 class Animal:
     2 
     3     def eat(self):
     4         print "%s 吃 " %self.name
     5 
     6     def drink(self):
     7         print "%s 喝 " %self.name
     8 
     9     def shit(self):
    10         print "%s 拉 " %self.name
    11 
    12     def pee(self):
    13         print "%s 撒 " %self.name
    14 
    15 
    16 class Cat(Animal):
    17 
    18     def __init__(self, name):
    19         self.name = name
    20         self.breed = ''
    21 
    22     def cry(self):
    23         print '喵喵叫'
    24 
    25 class Dog(Animal):
    26     
    27     def __init__(self, name):
    28         self.name = name
    29         self.breed = ''
    30         
    31     def cry(self):
    32         print '汪汪叫'
    33         
    34 
    35 # ######### 执行 #########
    36 
    37 c1 = Cat('小白家的小黑猫')
    38 c1.eat()
    39 
    40 c2 = Cat('小黑的小白猫')
    41 c2.drink()
    42 
    43 d1 = Dog('胖子家的小瘦狗')
    44 d1.eat()
    45 
    46 代码实例
    继承

    多继承,子类可以继承多个父类的函数,寻找时优先左继承

     1 class D(object):
     2 
     3     def bar(self):
     4         print 'D.bar'
     5 
     6 
     7 class C(D):
     8 
     9     def bar(self):
    10         print 'C.bar'
    11 
    12 
    13 class B(D):
    14 
    15     def bar(self):
    16         print 'B.bar'
    17 
    18 
    19 class A(B, C):
    20 
    21     def bar(self):
    22         print 'A.bar'
    23 
    24 a = A()
    25 # 执行bar方法时
    26 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
    27 # 所以,查找顺序:A --> B --> C --> D
    28 # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
    29 a.bar()
    30 
    31 新式类多继承
    继承
  3. 多态,python因为带多态,可以不用多深就。

 三,类的成员

  类可以分为三大类,字段,方法和属性。

   字段分为静态字段和普通字段。普通字段可以理解为类中的函数,而静态字段则不是。

    区别:访问区别,静态字段可以不通过对象直接访问,普通字段则需要创建实例,通过实例进行访问。

  • 普通字段属于对象
  • 静态字段属于

输出结果为,1和12

因为这个访问是从对象上进行访问,所以是先访问普通字段,然后在访问静态字段。

 

 1 class Province:
 2 
 3     # 静态字段
 4     country = '中国'
 5 
 6     def __init__(self, name):
 7 
 8         # 普通字段
 9         self.name = name
10 
11 
12 # 直接访问普通字段
13 obj = Province('河北省') #创建实例
14 print obj.name
15 
16 # 直接访问静态字段
17 Province.country
18 
19 字段的定义和使用

方法有三种:

  • 普通方法,由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
  • 静态方法,由调用;无默认参数
  • 类方法,由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
  •  1 class Foo:
     2 
     3     def __init__(self, name):
     4         self.name = name
     5 
     6     def ord_func(self):
     7         """ 定义普通方法,至少有一个self参数 """
     8 
     9         # print self.name
    10         print '普通方法'
    11 
    12     @classmethod
    13     def class_func(cls):
    14         """ 定义类方法,至少有一个cls参数 """
    15 
    16         print '类方法'
    17 
    18     @staticmethod
    19     def static_func():
    20         """ 定义静态方法 ,无默认参数"""
    21 
    22         print '静态方法'
    23 
    24 
    25 # 调用普通方法
    26 f = Foo()
    27 f.ord_func()
    28 
    29 # 调用类方法
    30 Foo.class_func()
    31 
    32 # 调用静态方法
    33 Foo.static_func()
    34 
    35 方法的定义和使用

     

属性

    

  13题的输出结果与14题的输出结果都为 <class '__main__.Foo'>。

  这表示访问类方法,不但可以从对象上进行访问,也可以从类进行访问。

Python中的属性其实是普通方法的变种。

    对于属性,有以下三个知识点:

      • 属性的基本使用
      • 属性的两种定义方式
      • 调用时,无需括号
                   方法:foo_obj.func()
                   属性:foo_obj.prop

     属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。

  属性的两种定义方法

  • 装饰器 即:在方法上应用装饰器
  • 静态字段 即:在类中定义值为property对象的静态字段

装饰器方式:在类的普通方法上应用@property装饰器

1 # ############### 定义 ###############    
2 class Goods:
3 
4     @property
5     def price(self):
6         return "wupeiqi"
7 # ############### 调用 ###############
8 obj = Goods()
9 result = obj.price  # 自动执行 @property 修饰的 price 方法,并获取方法的返回值

  新式类,具有三种@property装饰器

 1 # ############### 定义 ###############
 2 class Goods(object):
 3 
 4     @property
 5     def price(self):
 6         print '@property'
 7 
 8     @price.setter
 9     def price(self, value):
10         print '@price.setter'
11 
12     @price.deleter
13     def price(self):
14         print '@price.deleter'
15 
16 # ############### 调用 ###############
17 obj = Goods()
18 
19 obj.price          # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
20 
21 obj.price = 123    # 自动执行 @price.setter 修饰的 price 方法,并将  123 赋值给方法的参数
22 
23 del obj.price      # 自动执行 @price.deleter 修饰的 price 方法

  由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

 1 class Goods(object):
 2 
 3     def __init__(self):
 4         # 原价
 5         self.original_price = 100
 6         # 折扣
 7         self.discount = 0.8
 8 
 9     @property
10     def price(self):
11         # 实际价格 = 原价 * 折扣
12         new_price = self.original_price * self.discount
13         return new_price
14 
15     @price.setter
16     def price(self, value):
17         self.original_price = value
18 
19     @price.deltter
20     def price(self, value):
21         del self.original_price
22 
23 obj = Goods()
24 obj.price         # 获取商品价格
25 obj.price = 200   # 修改商品原价
26 del obj.price     # 删除商品原价
27 
28 实例

  

静态字段方式,创建值为property对象的静态字段

当使用静态字段的方式创建属性时,经典类和新式类无区别

 1 class Foo:
 2 
 3     def get_bar(self):
 4         return 'wupeiqi'
 5 
 6     BAR = property(get_bar)
 7 
 8 obj = Foo()
 9 reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
10 print reuslt

property的构造方法中有个四个参数

  • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
  • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
  • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
  • 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
     1 class Foo:
     2 
     3     def get_bar(self):
     4         return 'wupeiqi'
     5 
     6     # *必须两个参数
     7     def set_bar(self, value): 
     8         return return 'set value' + value
     9 
    10     def del_bar(self):
    11         return 'wupeiqi'
    12 
    13     BAR = property(get_bar, set_bar, del_bar, 'description...')
    14 
    15 obj = Foo()
    16 
    17 obj.BAR              # 自动调用第一个参数中定义的方法:get_bar
    18 obj.BAR = "alex"     # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
    19 del Foo.BAR          # 自动调用第三个参数中定义的方法:del_bar方法
    20 obj.BAE.__doc__      # 自动获取第四个参数中设置的值:description...

    由于静态字段方式创建属性具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除

     实例

     注意:Python WEB框架 Django 的视图中 request.POST 就是使用的静态字段的方式创建的属性

     Django源码

    所以,定义属性共有两种方式,分别是【装饰器】和【静态字段】,而【装饰器】方式针对经典类和新式类又有所不同。

四,类成员的修饰符

    

类的所有成员在上一步骤中已经做了详细的介绍,对于每一个类的成员而言都有两种形式:

  • 公有成员,在任何地方都能访问
  • 私有成员,只有在类的内部才能方法

私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)

1
2
3
4
5
class C:
 
    def __init__(self):
        self.name = '公有字段'
        self.__foo = "私有字段"

 

 

 

私有成员和公有成员的访问限制不同

静态字段

  • 公有静态字段:类可以访问;类内部可以访问;派生类中可以访问
  • 私有静态字段:仅类内部可以访问;
 公有静态字段
 私有静态字段

普通字段

  • 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
  • 私有普通字段:仅类内部可以访问;

ps:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。

 公有字段
 私有字段

方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用

ps:非要访问私有属性的话,可以通过 对象._类__属性名

五,嵌套

 类可以通过嵌套将两者类练习到一起。

 1 class School(object):
 2     def __init__(self, name, address):
 3         self.name = name
 4         self.address = address
 5 
 6     def speech(self):
 7         print('讲课')
 8 
 9 obj1 = School('老男孩北京校区', '美丽富饶的沙河')
10 obj2 = School('老男孩上海校区', '浦东新区')
11 obj3 = School('老男孩深圳校区', '南山区')
12 class Teacher(object):
13     def __init__(self, name, age, salary):
14         self.name = name
15         self.age = age
16         self.__salary = salary
17         self.school = None
18 
19 t1 = Teacher('李杰', 19, 188888)
20 t2 = Teacher('艳涛', 18, 60)
21 t3 = Teacher('女神',16, 900000)
22 # ############## 老师分配校区
23 t1.school = obj1  #t1与obj是来自两个不同的类,但是通过school练习到了一起。
24 t2.school = obj1
25 t3.school = obj2
26 # ####################################
27 # 查看t1老师,所在的校区名称/地址
28 print(t1.school.name) 
29 print(t1.school.address)
30 print(t1.name)
31 print(t1.age)
32 t1.school.speech()

 六,主动调用其他类的函数

  当子类的缺少函数时会被动的在父类那里找。但如果想主动的去父类找,则需要一些方法。

 ########### 方式一
# class Base(object):
#
#     def f1(self):
#         print('5个功能')
#
# class Foo(object):
#
#     def f1(self):
#         print('3个功能')
#         Base.f1(self)  
#
# obj = Foo()
# obj.f1()


# ########### 方式二:按照类的继承顺序,找下一个.
"""
class Base(object):
    def f1(self):
        print('5个功能')

class Foo(Base):
    def f1(self):
        super().f1()
        print('3个功能')
        
obj = Foo()
obj.f1()
"""

# ########### 方式二:按照类的继承顺序,找下一个.
class Foo(object):
    def f1(self):
        super().f1() #此时内部的self是Info
        print('3个功能')

class Bar(object):
    def f1(self):
        print('6个功能')

class Info(Foo,Bar):
    pass

# obj = Foo()
# obj.f1()

obj = Info()
obj.f1()

七,类的特殊成员

1. __doc__

  表示类的描述信息

1 class Foo:
2     """ 描述类信息,这是用于看片的神奇 """
3 
4     def func(self):
5         pass
6 
7 print Foo.__doc__
8 #输出:类的描述信息

 

2. __module__ 和  __class__ 

  __module__ 表示当前操作的对象在那个模块

  __class__     表示当前操作的对象的类是什么

#!/usr/bin/env python
# -*- coding:utf-8 -*-

class C:

    def __init__(self):
        self.name = 'wupeiqi'
复制代码

from lib.aa import C

obj = C()
print obj.__module__  # 输出 lib.aa,即:输出模块
print obj.__class__      # 输出 lib.aa.C,即:输出类

3. __init__

  构造方法,通过类创建对象时,自动触发执行。类+()会自动执行init

1 class Foo:
2 
3     def __init__(self, name):
4         self.name = name
5         self.age = 18
6 
7 
8 obj = Foo('wupeiqi') # 自动执行类中的 __init__ 方法

 

4. __del__

  析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

5. __call__

  类+()会执行init,而对象+()会执行call。  

  对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

 1 class Foo:
 2 
 3     def __init__(self):
 4         pass
 5     
 6     def __call__(self, *args, **kwargs):
 7 
 8         print '__call__'
 9 
10 
11 obj = Foo() # 执行 __init__
12 obj()       # 执行 __call__

 

6. __dict__

 可以获取封装的内容,以字典的形式呈现出来

 1 class Province:
 2 
 3     country = 'China'
 4 
 5     def __init__(self, name, count):
 6         self.name = name
 7         self.count = count
 8 
 9     def func(self, *args, **kwargs):
10         print 'func'
11 
12 # 获取类的成员,即:静态字段、方法、
13 print Province.__dict__
14 # 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
15 
16 obj1 = Province('HeBei',10000)
17 print obj1.__dict__
18 # 获取 对象obj1 的成员
19 # 输出:{'count': 10000, 'name': 'HeBei'}
20 
21 obj2 = Province('HeNan', 3888)
22 print obj2.__dict__
23 # 获取 对象obj1 的成员
24 # 输出:{'count': 3888, 'name': 'HeNan'}

 

 7. __str__

  如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

1 class Foo:
2 
3     def __str__(self):
4         return 'wupeiqi' #只能填写字符串
5 
6 
7 obj = Foo()
8 print obj #将内存地址换成了字符串
9 # 输出:wupeiqi

8、__getitem__、__setitem__、__delitem__

用于索引操作,如字典。以上分别表示获取、设置、删除数据

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3  
 4 class Foo(object):
 5  
 6     def __getitem__(self, key):
 7         print '__getitem__',key
 8  
 9     def __setitem__(self, key, value):
10         print '__setitem__',key,value
11  
12     def __delitem__(self, key):
13         print '__delitem__',key
14  
15  
16 obj = Foo()
17  
18 result = obj['k1']      # 自动触发执行 __getitem__
19 obj['k2'] = 'wupeiqi'   # 自动触发执行 __setitem__
20 del obj['k1']           # 自动触发执行 __delitem__

 

9、__getslice__、__setslice__、__delslice__

 该三个方法用于分片操作,如:列表

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3  
 4 class Foo(object):
 5  
 6     def __getslice__(self, i, j):
 7         print '__getslice__',i,j
 8  
 9     def __setslice__(self, i, j, sequence):
10         print '__setslice__',i,j
11  
12     def __delslice__(self, i, j):
13         print '__delslice__',i,j
14  
15 obj = Foo()
16  
17 obj[-1:1]                   # 自动触发执行 __getslice__
18 obj[0:1] = [11,22,33,44]    # 自动触发执行 __setslice__
19 del obj[0:2]                # 自动触发执行 __delslice__

 

10. __iter__ ,可以通过加入iter使不可迭代对象变成可迭代的。

用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__ 

 1 复制代码
 2 class Foo(object):
 3     pass
 4 
 5 
 6 obj = Foo()
 7 
 8 for i in obj:
 9     print i
10     
11 # 报错:TypeError: 'Foo' object is not iterable
12 复制代码
13 
14 复制代码
15 #!/usr/bin/env python
16 # -*- coding:utf-8 -*-
17 
18 class Foo(object):
19     
20     def __iter__(self):
21         pass
22 
23 obj = Foo()
24 
25 for i in obj:
26     print i
27 
28 # 报错:TypeError: iter() returned non-iterator of type 'NoneType'
29 复制代码
30 
31 复制代码
32 #!/usr/bin/env python
33 # -*- coding:utf-8 -*-
34 
35 class Foo(object):
36 
37     def __init__(self, sq):
38         self.sq = sq
39 
40     def __iter__(self):
41         return iter(self.sq)
42 
43 obj = Foo([11,22,33,44])
44 
45 for i in obj:
46     print i

以上步骤可以看出,for循环迭代的其实是  iter([11,22,33,44]) ,所以执行流程可以变更为:

1 #!/usr/bin/env python
2 # -*- coding:utf-8 -*-
3  
4 obj = iter([11,22,33,44])
5  
6 for i in obj:
7     print i

 

11. __new__ 和 __metaclass__

阅读以下代码:

1 class Foo(object):
2  
3     def __init__(self):
4         pass
5  
6 obj = Foo()   # obj是通过Foo类实例化的对象

 

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

1
2
print type(obj) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type 'type'>              表示,Foo类对象由 type 类创建

八,构造方法

创建类就可以有两种方式:

 1 a). 普通方式
 2 
 3 class Foo(object):
 4  
 5     def func(self):
 6         print 'hello wupeiqi'
 7 b).特殊方式(type类的构造函数)
 8 
 9 
10 def func(self):
11     print 'hello wupeiqi'
12  
13 Foo = type('Foo',(object,), {'func': func})
14 #type第一个参数:类名
15 #type第二个参数:当前类的基类
16 #type第三个参数:类的成员

 

 

==》 类 是由 type 类实例化产生

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

 1  1 真正的构造方法
 2  2 # class Foo(object):
 3  3 #     def __init__(self, a1, a2):     # 初始化方法
 4  4 #         """
 5  5 #         为空对象进行数据初始化
 6  6 #         :param a1:
 7  7 #         :param a2:
 8  8 #         """
 9  9 #         self.a1 = a1
10 10 #         self.a2 = a2
11 11 #
12 12 #     def __new__(cls, *args, **kwargs): # 构造方法
13 13 #         """
14 14 #         创建一个空对象
15 15 #         :param args:
16 16 #         :param kwargs:
17 17 #         :return:
18 18 #         """
19 19 #         return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.). #必须有return
20 20 #
21 21 # obj1 = Foo(1,2)
22 22 # print(obj1)

九,函数补充(issubclass、type)

  •  1 class Base(object):
     2     pass
     3 
     4 class Foo(Base):
     5     pass
     6 
     7 class Bar(Foo):
     8     pass
     9 
    10 print(issubclass(Bar,Base)) # 检查第一个参数是否是第二个参数的 子子孙孙类

    判断类之间是否有父类与子类的关系

  • 1 class Foo(object):
    2     pass
    3 
    4 obj = Foo()
    5 
    6 print(obj,type(obj)) # 获取当前对象是由那个类创建。
    7 if type(obj) == Foo:
    8     print('obj是Foo类型')

    判断对象与类时候有关系(不包括类的父类)(更加精准)

  •  1 class Base(object):
     2     pass
     3 
     4 class Foo(Base):
     5     pass
     6 
     7 obj1 = Foo()
     8 print(isinstance(obj1,Foo))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
     9 print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    10 
    11 
    12 obj2 = Base()
    13 print(isinstance(obj2,Foo))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
    14 print(isinstance(obj2,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。

    判断对象与类时候有关系(包括类的父类)(更加模糊)

十,易错点

  在类中可以分为静态字段与普通字段。并且静态字段属于类,普通字段属于对象。而,两者的更深层次的区分原因是两者的在执行时所在的内存地址不同。属于类的静态字段会在类的内存上创建,而属于对象的普通字段会在对象的内存中创建。下面三题由浅到深的进行了讲解。

 1 第一题:
 2 
 3 class StarkConfig(object):
 4     list_display = []
 5 
 6     def get_list_display(self):
 7         self.list_display.insert(0,33)
 8         return self.list_display
 9 
10 
11 s1 = StarkConfig()#进行对象化
12 
13 result1 = s1.get_list_display()
14 print(result1) # 33
15 
16 result2 = s1.get_list_display()
17 print(result2) # 33 33

 我们可以看出静态字段是在类StarkConfig的内存地址中。

 

 1 class StarkConfig(object):
 2    3 
 4     def get_list_display(self):
 5         self.list_display.insert(0,33)
 6         return self.list_display
 7 
 8 
 9 s1 = StarkConfig()
10 s2 = StarkConfig()
11 
12 result1 = s1.get_list_display()
13 print(result1)
14 
15 result2 = s1.get_list_display()
16 print(result2)

 

 创建完对象后会执行_init_函数,此时会在对象地址上进行创建。

 1 class StarkConfig(object):
 2     list_display = []
 3 
 4     def get_list_display(self):
 5         self.list_display.insert(0,33)
 6         return self.list_display
 7 
 8 
 9 s1 = StarkConfig()
10 s2 = RoleConfig()
11 
12 result1 = s1.get_list_display()
13 print(result1) #33
14 
15 result2 = s2.get_list_display()
16 print(result2) #33

会在两个内存地址个创建一个列表进行填数。

 

posted on 2023-12-07 02:56  我才是最帅的那个男人  阅读(42)  评论(0)    收藏  举报

导航