二十一、 Python 面向对象基础(二) -- 类成员、修饰符、特殊成员

 

一、类成员

   类成员可以分为3类:字段,方法和属性。

   字段:静态字段、普通字段

   方法:静态方法、普通方法、类方法

   属性:普通属性

 

  通过类访问:静态字段、 静态方法、类方法、

  通过对象访问:普通字段,类普通方法、类特性

 

 所有的成员中:只有普通字段内容保存在对象中。即:根据此类创建了多少对象,在内存中就有多少普通字段。

                      其他的成员则保存在类中。即:无论对象多少,在内存中仅创建一份。

 

 

二、字段

 字段包括:普通字段和静态字段。他们在定义和使用中有区别。本质区别为在内存中保存的位置不同。

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

   静态字段,将每个对象重复的东西放到类中。

   访问规则:谁的成员谁访问。对象的成员用对象访问。类的成员用类访问,除了类中的方法。

  

 1 class Province:
 2 
 3     #静态字段
 4     country = '中国'
 5 
 6     def __init__(self,name):
 7 
 8         #普通字段
 9         self.name = name
10 
11 #直接访问普通字段
12 obj = Province('河北')
13 print(obj.name)
14 
15 #直接访问静态字段
16 print(Province.country)
17 
18 #也可以通过对象访问静态字段,但是不推荐
19 print(obj.country)

 从上图可以看出

  • 静态字段内存中只保存一份
  • 普通字段在每个对象都保存一份

 

 

三、方法

  方法包括:普通方法、静态方法和类方法。 3种方法 都内存中都归属于类。 区别在于调用方式不同。

  普通方法:由对象调用,至少一个self参数;执行普通参数的时候,自动调用该方法的对象,赋值给self

  静态方法:由调用,无默认参数。

  类方法:由调用;至少一个cls参数。在执行的时候,自动调用该类赋值个给cls

 

  静态方法:仅仅属于该类,类似函数工具库的作用。可以直接使用,不需要类的实例调用

  类方法:将类作为参数传递,主要用来获取和类相关的一些数值

 

 1 class Foo:
 2 
 3     def __init__(self,name):
 4         self.name = name
 5 
 6     def ord_func(self):
 7 
 8         """
 9         定义普通方法,至少一个self参数
10         :return:
11         """
12         #print self.name
13 
14         print('普通方法')
15 
16     @classmethod
17 
18     def class_fun(cls):
19         """
20         定义类方法,至少有一个cls 参数
21         :return:
22         """
23         print('类方法')
24         print(dir(cls))
25 
26     @staticmethod
27     def static_func():
28         """静态方法,无默认参数"""
29         print('静态方法')
30 
31 
32 #调用普通方法
33 f = Foo('yy')
34 f.ord_func()
35 
36 #调用类方法
37 Foo.class_fun()
38 
39 #调用静态方法
40 Foo.static_func()
41 
42 
43 C:\Python35\python.exe D:/python/day8/pr.py
44 普通方法
45 类方法
46 ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'class_fun', 'ord_func', 'static_func']
47 静态方法

  

相同点:对于所有方法而言,均属于类中。所以在内存中也只保存一份。

 不同点:方法调用者不同。调用方法时传递的参数不同

 

四、属性

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

  •  属性的基本使用
  •  属性的两种定义方式

 1:属性的基本使用

 1 class Foo:
 2 
 3     def __init__(self,name):
 4         self.name = name
 5 
 6     def ord_func(self):
 7 
 8         """
 9         定义普通方法,至少一个self参数
10         :return:
11         """
12         #print self.name
13 
14         print('普通方法')
15 
16     @property
17     def start(self):
18         temp = '%s '%self.name
19         print(temp)
20 
21 
22 #调用普通方法
23 f = Foo('yy')
24 
25 #直接使用特性名称访问
26 f.start

 

属性的定义和使用的注意点:

定义时,在普通方法的基础上添加 @property 装饰器

定义时,仅仅有self一个参数

调用方法的时候,无需()

 

属性存在的意义: 访问属性时可以制造出和访问字段相同的假象。

             

2、属性的定义

(此部分,需要参考老师博客http://www.cnblogs.com/wupeiqi/p/4766801.html)

装饰器:在方法上应用property装饰器

1     @property
2     def start(self):
3         temp = '%s '%self.name
4         print(temp)

 

静态字段:定义只为property对象的静态字段

1 BAR = property(get_bar)

 

五、成员修饰符

类的所有成员,对于访问分2种:

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

 

1:私有成员和公有成员定义不同

私有成员命名时:前2个字符是下划线(特殊成员除外:__init__, __call__, __dict__等)

 

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

静态字段

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

 

普通字段

  • 公有普通字段: 对象可以访问;类内部可以访问;派生类可以访问
  • 私有普通字段:仅类内部可以访问
  • 如果要强制访问私有字段,可以使用【对象.__类名称__私有字段】 访问
  •  1 class Foo:
     2 
     3     def __init__(self):
     4         self.name = '公有字段'
     5         self.__foo = '私有字段'
     6 
     7     def Foo_f1(self):
     8         print(self.__foo)
     9 
    10 class B(Foo):
    11     def F1(self):
    12         print(self.name)
    13         #派生类调用父类私有字段报错
    14         #print(self.__foo)
    15 
    16         #强制访问
    17         print(self._Foo__foo)
    18 
    19 obj1 = Foo()
    20 obj2 = B()
    21 #对象调用普通公有字段
    22 print(obj1.name)
    23 print(obj2.name)
    24 #对象调用普通私有字段报错
    25 # print(obj1.__foo)
    26 # print(obj2.__foo)
    27 
    28 #类内部可以调用私有字段
    29 obj1.Foo_f1()
    30 obj2.Foo_f1()
    31 obj2.F1()
    32 
    33 
    34 #强制访问
    35 obj1._Foo__foo

     

静态字段

  • 普通静态字段
  • 私有静态字段
  • 如果要强制访问私有字段,可以使用【对象.__类名称__私有字段】 访问
 1 class Foo:
 2     age = '公有静态'
 3     __sex = '私有静态'
 4     def __init__(self):
 5         self.name = '公有字段'
 6         self.__foo = '私有字段'
 7 
 8     def Foo_f1(self):
 9         print(Foo.age)
10         print(Foo.__sex)
11 
12 class B(Foo):
13     def F1(self):
14         print(self.name)
15         #派生类调用父类私有字段报错
16         # print(self.__foo)
17 
18         #强制访问
19         print(self._Foo__foo)
20 
21         #强制访问
22         print(self._Foo__sex)
23 
24 
25 
26 obj1 = Foo()
27 obj2 = B()
28 
29 #公有静态类可以访问
30 print(Foo.age)
31 
32 #私有静态,类直接访问报错
33 # print(Foo.__sex)
34 
35 #公有静态类内部可以访问
36 #私有静态类内可以直接访问
37 obj1.Foo_f1()
38 
39 #公有静态派生类可以访问
40 print(obj2.name)
41 
42 #私有静态派生类访问直接报错
43 # print(obj2.__sex)
44 
45 
46 obj2.F1()

 

方法

 普通方法

  •  普通公有方法: 在对象、类内部、派生类访问
  •  普通私有访问:仅仅在内内部访问
  • 如果要强制访问私有字段,可以使用【对象.__类名称__私有字段】 访问
 1 class Foo:
 2 
 3     def __init__(self):
 4         self.name = '公有字段'
 5         self.__foo = '私有字段'
 6 
 7     def Foo_f1(self):
 8         print('普通公有方法')
 9 
10     def __Foo_f2(self):
11         print('普通私有方法')
12 
13 
14     def Foo_f3(self):
15         self.__Foo_f2()
16 
17     @staticmethod
18     def static_method():
19         print('静态方法')
20 
21 
22 
23 
24 
25 class B(Foo):
26     def F1(self):
27         self.Foo_f1()
28         
29         #强制调用普通私有
30         self._Foo__Foo_f2()
31 
32 
33 obj1 = Foo()
34 obj2 = B()
35 
36 #对象调用普通访问
37 obj1.Foo_f1()
38 
39 #对象调用普通私有报错
40 # obj1.__Foo_f2()
41 
42 #类内部调用普通私有方法
43 obj1.Foo_f3()
44 
45 obj2.F1() 

 

 静态方法

  •  静态公有方法: 在对象、类内部、派生类访问
  •  静态私有访问:仅仅在内内部访问
  • 如果要强制访问私有字段,可以使用【对象.__类名称__私有字段】 访问
 1 class Foo:
 2 
 3     def __init__(self):
 4         self.name = '公有字段'
 5         self.__foo = '私有字段'
 6 
 7     @staticmethod
 8     def Foo_f1():
 9         print('静态公有方法')
10 
11     @staticmethod
12     def __Foo_f2():
13         print('静态私有方法')
14 
15 
16     def Foo_f3(self):
17         self.__Foo_f2()
18 
19 
20 class B(Foo):
21     def F1(self):
22         self.Foo_f1()
23 
24         #强制调用普通私有
25         self._Foo__Foo_f2()
26 
27 
28 obj1 = Foo()
29 obj2 = B()
30 # 类中直接调用静态公有方法
31 Foo.Foo_f1()
32 
33 # 类内部调用静态私有方法访问
34 obj1.Foo_f3()
35 
36 #派生类调用静态公有,强制调用静态私有
37 obj2.F1()

 

 在属性上,与字段和方法类似

 

  六、类的特殊成员

类中有字段、字段、属性三大类成员

如果成员前有两个下环线,表示该成员是私有成员,私有成员只能用于类内部调用。 

但是也存在一些特殊含义的成员

1:__doc__

   输出类的描述信息

 1 class Foo():
 2     """  查看类的doc """
 3 
 4     def func(self):
 5         pass
 6 
 7 
 8 obj1 = Foo()
 9 print(Foo.__doc__)
10 print(obj1.__doc__)

 

2:__module__ 和 __class__

   __module__当前操作的对象在哪个模块

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

class Foo():
    """  查看类的doc """

    def func(self):
        pass


obj1 = Foo()
print(Foo.__module__)
print(obj1.__module__)
print(Foo.__class__)
print(obj1.__class__)


C:\Python35\python.exe D:/python/day8/pr.py
__main__
__main__
<class 'type'>
<class '__main__.Foo'>

 

3、__init__

  构造方法,通过类创建对象的时候,自动触发执行

 

1 class Foo():
2     """  查看类的doc """
3 
4     def func(self):
5         pass
6     def __init__(self):
7         print('我是构造函数')
8 
9 obj1 = Foo()  #自动触发__init__

 

4、__del___

  解析防范,在对象被释放的时候,自动触发

  此方法不需要定义。python在进行垃圾回收的时候自动触发执行

 

5、__call__

 对象后面加(),触发执行

  • 构造方法的执行是有创建对象触发的。即: 对象= 类名()
  • 对于__call__的方法的执行是有对象后加()触发执行,即对象() 或者类()

 

 1 class Foo():
 2     def func(self):
 3         pass
 4     def __init__(self):
 5         print('我是构造函数')
 6 
 7     def __call__(self):
 8         print('我是call函数')
 9 
10 obj1 = Foo()  #自动触发__init__
11 
12 # 对象后加()触发执行__call__
13 obj1()
14 
15 #类后加()触发执行__call__
16 Foo()()
17 
18 C:\Python35\python.exe D:/python/day8/pr.py
19 我是构造函数
20 我是call函数
21 我是构造函数
22 我是call函数

 

6、__dict__

 显示对象或者类中所有成员

普通字段属于对象,静态字段和方法属于类。

 1 class Foo():
 2     name = 'Foo'
 3 
 4     def __init__(self,age):
 5         self.age = age
 6 
 7 obj1 = Foo(18)
 8 
 9 #获取类所有的成员  :静态成员和方法
10 print(Foo.__dict__)
11 
12 #{'__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__init__': <function Foo.__init__ at 0x009D4F60>, '__dict__': <attribute '__dict__' of 'Foo' objects>, 'name': 'Foo', '__module__': '__main__', '__doc__': None}
13 
14 #获取对象的成员
15 print(obj1.__dict__)
16 #{'age': 18}

 

7、__str__

  打印对象,默认返回对象的地址

  如果类中定义了__str__, 在打印对象的时候, 返回该方法返回值

  

 1 class Foo():
 2     name = 'Foo'
 3 
 4     def __init__(self,age):
 5         self.age = age
 6 
 7     def __str__(self):
 8         return '我是一个字符串'
 9 
10 obj1 = Foo(18)
11 print(obj1)
12 # 未定义__str__ <__main__.Foo object at 0x005995D0>
13 
14 #添加 __str__ 后返回 我是一个字符串

 

8、 __gettiem__  __setitem__  __delitem__

  用于索引上进行操作,如字段。以上分别为获取、设置、删除数据

 

 1 class Foo:
 2 
 3    def __init__(self,name):
 4        self.name = name
 5 
 6    def __getitem__(self,item):
 7        print(item)
 8 
 9    def __setitem__(self,item,value):
10        print(item,value)
11 
12    def __delitem__(self,key):
13        print(key)
14 
15 obj1 = Foo('kk')
16 
17 #对象后【】 调用 __getitem__
18 result = obj1['k1']
19 
20 #自动执行__setitem__
21 obj1['k2'] = 123
22 
23 #自动执行__delitem__
24 del obj1['k2']

 

9、__getslice__ __setslice__ __delslice__

   上面3个方法用于切片操作(python2.7)

   在3.5中,3个功能被 __getitem__  __setitem__ __delitem__ 替换

   

 1 class Foo:
 2 
 3    def __init__(self,name):
 4        self.name = name
 5 
 6    def __getitem__(self,item):
 7        print(type(item),item, '__getitem__')
 8 
 9    def __setitem__(self,item,value):
10        print(item,value,'__setitem__')
11 
12    def __delitem__(self,key):
13        print(key,'__delitem__')
14 
15 obj1 = Foo('kk')
16 
17 #调用 __getitem__  <class 'slice'> slice(1, 3, None) __getitem__
18 result = obj1[1:3]
19 
20 #自动执行__setitem__
21 obj1[1,2] = [11,22]
22 
23 #自动执行__delitem__
24 del obj1[1,2]
25 
26 
27 C:\Python35\python.exe D:/python/day8/pr.py
28 <class 'slice'> slice(1, 3, None) __getitem__
29 (1, 2) [11, 22] __setitem__
30 (1, 2) __delitem__

 

 10、__iter__

  用于迭代器,列表、字段、元组都可以进行迭代,是因为内部定义了__inter__

 如果for对象,直接执行 对象内部的__iter__

 

  有2中方式: 在__iter__应用yield

                   在__iter__iter 返回迭代器

 1 class Foo(object):
 2 
 3     def __init__(self,sq):
 4         self.sq = sq
 5 
 6     #第一种方式
 7     def __iter__(self):
 8         yield 1
 9         yield 2
10         yield 3
11 
12     #第二种方式
13     def __iter__(self):
14         return iter(self.sq)
15 
16 obj1 = Foo([11,22,33,44])
17 
18 for i in obj1:
19     print(i)

 

11: __new__ 和 __metaclass__

   __new__ 创建类实例

   __metaclass__ 指定类由哪个类创建

   类本身也是对象。类是type 类的实例

   

 1 #普通方式
 2 class Foo(object):
 3 
 4     def func1(self):
 5         print('Foo')
 6 
 7 
 8 obj1 = Foo()
 9 obj1.func1()
10 
11 #特殊方式,type创建
12 def func(self):
13     print('bar')
14 
15 Bar = type('Bar',(object,),{'func':func})
16 
17 #type 第一个参数,类名称
18 #type 第二个参数,当前类的基类
19 #type 第三个参数,类的成员
20 
21 obj2 = Bar()
22 obj2.func()

  

 

posted @ 2016-06-18 22:25  咖啡茶  阅读(113)  评论(0)    收藏  举报