zoukankan      html  css  js  c++  java
  • 面向对象(二)

    类的成员

    类的成员可以分为三大类:字段、方法和属性

    一、字段

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

    • 普通字段属于对象,在内存中为每个对象保存一份
    • 静态字段属于类,在内存中只保存一份

    一般情况下,自己访问自己字段,普通字段只能使用对象访问,静态字段使用类访问(最好不要用对象访问静态字段),静态字段在代码加载时创建。

    #!/usr/bin/env python
    # coding=utf-8
    
    
    class Province(object):
    
        # 静态字段,保存在类中
        country = '中国'
    
        def __init__(self, province):
            # 普通字段,保存在对象中
            self.name = 'province'
        # 普通方法,由对象去调用执行(方法属于类)
        def show(self):
            return self.name
    
        # 静态方法,由类调用执行,对象是封装数据的,用不到对象封装数据,使用静态方法
        @staticmethod
        def f1():
            return '....'
    
    test = Province('henan')
    print(Province.country)
    print(test.country)
    print(test.show())
    
    print(Province.f1())
    View Code

    应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

    二、方法

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

    • 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self
    • 类方法:由调用; 至少一个cls参数;执行类方法时,自动将调用该方法的复制给cls
    • 静态方法:由调用;无默认参数;
    #!/usr/bin/env python
    # coding=utf-8
    
    # 面向对象中类成员
    # 字段: 静态字段, 普通字段
    # 方法:  普通方法 静态方法, 类方法
    #      所有方法属于类
    #      普通方法:至少一个self,对象执行
    #      静态方法:任意参数, 类执行(对象执行,基本不要用)
    #      类方法: 至少一个cls,类执行(对象执行,基本不要用)
    # 属性: 看pager.py  (@property)
    #       具有方法的写作形式,具有字段的访问形式
    
    class Province(object):
    
        # 静态字段,保存在类中
        country = '中国'
    
        def __init__(self, province):
            # 普通字段,保存在对象中
            self.name = 'province'
        # 普通方法,由对象去调用执行(方法属于类)
        def show(self):
            return self.name
    
        # 静态方法,由类调用执行,对象是封装数据的,用不到对象封装数据,使用静态方法
        # 可以有参数,可以没有
        @staticmethod
        def f1():
            return '....'
    
        # 类方法
        # 必须有一个参数cls, cls是类名  加()创建对象
        @classmethod
        def f2(cls):
            print(cls.country)
            print(cls)
    
    test = Province('henan')
    print(Province.country)
    print(test.country)
    print(test.show())
    
    
    print(Province.f1())
    
    Province.f2()
    View Code 

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

    不同点:方法调用者不同、调用方法时自动传入的参数不同。

    三、属性

    属性定义有两种方式

    1. 装饰器 在方法上应用装饰器
      #!/usr/bin/env python
      # coding=utf-8
      
      class Pager(object):
      
          def __init__(self, page):
              self.all_count = page
      
          # 获取
          @property
          def all_pager(self):
              a1, a2 = divmod(self.all_count, 10)
              if a2 == 0:
                  return a1
              else:
                  return a1 + 1
          # 设置
          @all_pager.setter
          def all_pager(self, value):
              print(value)
      
          # 删除
          @all_pager.deleter
          def all_pager(self):
              print('del all_pager')
      
      
      p = Pager(101)
      ret = p.all_pager  # 自动去执行Pager里面的@property下的all_pager方法,下同
      print(ret)
      
      p.all_pager = 111
      
      del p.all_pager
      View Code
    1. 静态字段 在类中定义为property对象的静态字段
       1 #!/usr/bin/env python
       2 # coding=utf-8
       3 class Pager:
       4     def __init__ (self, all_count):
       5         self.all_count = all_count
       6     def f1(self):
       7         return 123
       8     def f2(self, value):
       9         pass
      10     def f3(self):
      11         pass
      12     foo = property(fget=f1, fset=f2, fdel=f3)
      13 p = Pager(101)
      14 ret = p.foo # 执行fget
      15 print(ret)
      16 p.foo = 'hexm'  # 执行fset
      17 del p.foo   # 执行fdel
      View Code

    类成员修饰符

    对于每一个类的成员而言都有两种形式:

    • 公有成员,在任何地方都能访问
    • 私有成员,只有在类的内部才能方法
     1 class Foo(object):
     2     __cc = '123'    # 公有静态字段
     3 
     4     def __init__(self, name):
     5         # 私有的,只能在类内部访问
     6         self.__name = name    # 私有字段
     7 
     8     def f1(self):
     9         print(self.__name)
    10 
    11     def f2(self):
    12         print(Foo.__cc)
    13 
    14 obj = Foo('hexm')
    15 obj.f1()
    16 # print(obj.__name)  # 错误
    17 print(obj._Foo__name)  # 最好不要用这种方式访问私有字段
    18 
    19 obj.f2()
    20 print(Foo.f1__cc)
    21 
    22 # 继承Foo也不能访问私有的
    23 class Bar(Foo):
    24     def f2(self):
    25         print(self.__name)
    26 
    27 obj = Bar('hexm')
    28 obj.f1()
    29 obj.f2()  # 错误
    View Code

    类的特殊成员

    上面介绍了Python的类成员以及成员修饰符,从而了解到类中有字段、方法和属性三大类成员,并且成员名前如果有两个下划线,则表示该成员是私有成员,私有成员只能由类内部调用。无论人或事物往往都有不按套路出牌的情况,Python的类成员也是如此,存在着一些具有特殊含义的成员,详情如下:

    1. __doc__

      表示类的描述信息

    1 class Foo:
    2     """ 描述类信息 """
    3 
    4     def func(self):
    5         pass
    6 
    7 print Foo.__doc__
    View Code

    2. __module__ 和  __class__ 

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

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

    1 #!/usr/bin/env python
    2 # -*- coding:utf-8 -*-
    3 
    4 class C(object):
    5 
    6     def __init__(self):
    7         self.name = 'hexm'
    lib/a.py
    1 from lib.aa import C
    2 
    3 obj = C()
    4 print obj.__module__  # 输出 lib.aa,即:输出模块
    5 print obj.__class__      # 输出 lib.aa.C,即:输出类
    index.py

    3. __init__

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

    4. __del__

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

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

    5.__call__

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

     1 class Foo(object):
     2     def __init__(self):
     3         # 构造方法,创建对象自动执行
     4         print('init')
     5     def __del__(self):
     6         # 析构方法
     7         pass
     8     def __call__(self):
     9         print('call')
    10 p = Foo()
    11 ret = p.__class__
    12 print(ret)
    13 p()  # 对象后面加括号,执行__call__方法
    14 Foo()()  # 先执行构造方法再执行call
    View Code

    6.__dict__

    类或对象里面所有成员

     1 class Foo:
     2     def __init__(self, name, age):
     3         self.name = name
     4         self.age = age
     5     def __call__(self):
     6         return 123
     7 test1 = Foo('hexm', 18)
     8 test2 = Foo('zhuxj', 17)
     9 # 对象里面封装的字段
    10 ret = test1.__dict__
    11 print(ret)
    12 # 类里面所有成员
    13 print(Foo.__dict__)
    View Code

    7.__str__

    在类中定义了__str__方法,在打印对象时,默认输出该方法的返回值

     1 #!/usr/bin/env python
     2 # coding=utf-8
     3 class Foo:
     4     def __init__(self, name, age):
     5         self.name = name
     6         self.age = age
     7     def __str__(self):
     8         #  print 对象时,自动执行该方法
     9         return '%s---%s' % (self.name, self.age)
    10 test1 = Foo('hexm', 18)
    11 test2 = Foo('zhuxj', 17)
    12 print(test1)
    13 print(test2)
    14 ret1 = str(test1)
    15 ret2 = str(test2)
    16 print(ret1)
    17 print(ret2)
    View Code

    8.__getitem__、__setitem__、__delitem__

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

     1 #!/usr/bin/env python
     2 # coding=utf-8
     3 class Foo:
     4     def __init__(self, name, age):
     5         self.name = name
     6         self.age = age
     7     def __str__(self):
     8         #  print 对象时,自动执行该方法
     9         return '%s---%s' % (self.name, self.age)
    10     def __getitem__(self, item):
    11         if type(item) == slice:
    12             print(item.start)
    13             print(item.stop)
    14             print(item.step)
    15         elif type(item) == str:
    16             print(item)
    17     def __setitem__(self, key, value):
    18      #   print(type(key), type(value))
    19         if type(key) == slice:
    20             print(key,value)
    21     def __delitem__(self, key):
    22         print(type(key))
    23 test1 = Foo('hexm', 18)
    24 test1['sb']   # 执行__getitem__  字符串类型
    25 test1[1:3:1]    # 执行__getitem__   slice类型
    26 test1['k1'] = 'hexm'  # 执行 __setitem__
    27 test1[1:4] = [1, 2, 3, 4]
    28 del test1['k1']  # 执行 __delitem__
    29 del test1[1:4]
    View Code

    9.__iter__

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

    1 #!/usr/bin/env python
    2 # coding=utf-8
    3 class Foo:
    4     def __iter__(self):
    5         return iter([1, 2, 3, 4])
    6 test = Foo()
    7 #  把对象放到for循环中,会自动执行__iter__方法, 返回的值得可迭代对象
    8 for item in test:
    9     print(item)
    View Code

    10. __add__, __del__

    在类中定义__add__, __del__时,执行两个对象相加,执行__add__,两个对象相减,执行__del__

    1 def __add__(self, lover):
    2     xxx
    View Code

    11. issbuclass, isinstance

     1 #!/usr/bin/env python
     2 # coding=utf-8
     3 class Foo:
     4     def __iter__(self):
     5         return iter([1, 2, 3, 4])
     6 
     7 class Fo(Foo):
     8     pass
     9 test = Foo()
    10 # 对象是否属于某个类
    11 ret = isinstance(test, Foo)
    12 print(ret)
    13 ret = isinstance(test, Fo)
    14 print(ret)
    15 # 一个类是否是另一个类的子类
    16 ret = issubclass(Fo, Foo)
    17 print(ret)
    View Code

    12.__enter__

    python使用with-as语法,就会调用__enter__函数,然后把函数的return值传给as后指定的变量。然后执行with-as下的语句,无论出现了什么异常,都会在离开时执行__exit__

    为了让一个对象兼容with语句,需要实现__enter__()__exit__()方法。

     1 from socket import socket, AF_INET, SOCK_STREAM
     2 class LazyConnection:
     3     def __init__(self, address, family=AF_INET, type=SOCK_STREAM):
     4         self.address = address
     5         self.family = family
     6         self.type = type
     7         self.connections = []
     8     def __enter__(self):
     9         sock = socket(self.family, self.type)
    10         sock.connect(self.address)
    11         self.connections.append(sock)
    12         return sock
    13     def __exit__(self, exc_ty, exc_val, tb):
    14         self.connections.pop().close()
    15 # Example use
    16 from functools import partial
    17 conn = LazyConnection(('www.python.org', 80))
    18 with conn as s1:
    19     pass
    20     with conn as s2:
    21         pass
    22         # s1 and s2 are independent sockets
    View Code

    创建大量对象时节省内存方法

    如果程序要创建(上百万)大量对象,导致占用很大内存。可以给类添加__slots__属性来极大减少实例所占的内存。使用slots后不能给实例添加新的属性了,只能使用在__slots__中定义的那些属性名。

    比如:

    #!/usr/bin/env python
    # coding=utf-8
    
    class Date(objct):
        __slot__ = ['year', 'month', 'day']
        def __init__(self, year, month, day):
            self.year = year
            self.month = month
            self.day = day

     

     

  • 相关阅读:
    HDU 2196 Computer
    HDU 1520 Anniversary party
    POJ 1217 FOUR QUARTERS
    POJ 2184 Cow Exhibition
    HDU 2639 Bone Collector II
    POJ 3181 Dollar Dayz
    POJ 1787 Charlie's Change
    POJ 2063 Investment
    HDU 1114 Piggy-Bank
    Lca hdu 2874 Connections between cities
  • 原文地址:https://www.cnblogs.com/xiaoming279/p/6102514.html
Copyright © 2011-2022 走看看