zoukankan      html  css  js  c++  java
  • python--DAY7面向对象进阶

    静态方法:

      @staticmethod 实际上,静态方法与类没有实质上的关系,相当于类的一个工具包

    类方法:

      @classmethod 只能访问类变量,不能访问示例变量

    属性方法:

      @property 把一个方法,变成一个静态属性,调用时只能d.eat或d.eat = "包子",不能加括号,具体使用方法如下:

    class Dog(object):
        def __init__(self, name):
            self.name = name
            self.__food = None
    
        @property
        def eat(self):
            print("%s is eating %s" % (self.name, self.__food))
    
        @eat.setter
        def eat(self, food):
            print("set to food:", food)
            self.__food = food
    
        @eat.deleter
        def eat(self):
            del self.__food
            print("删除")
    
    
    d = Dog("小熊")
    d.eat = "包子"
    del d.eat
    d.eat  #已删除,会报错
    

     属性方法的使用场景:

      假设我们做一个航班的类,实例化的过程中会赋予对象一些属性,那么航班状态这个属性是随着时间变化实时更新的,这种情况下,使用静态属性明显得不到我们想要实现的功能,所以这种场景可以使用属性方法。每一次调用对象属性,都会去执行属性方法,获得当前最新的状态。

    定义航班类:

    class Flight(object):
        def __init__(self,name):
            self.flight_name = name
    
    
        def checking_status(self):
            print("checking flight %s status " % self.flight_name)
            return  1
    
        @property
        def flight_status(self):
            status = self.checking_status()
            if status == 0 :
                print("flight got canceled...")
            elif status == 1 :
                print("flight is arrived...")
            elif status == 2:
                print("flight has departured already...")
            else:
                print("cannot confirm the flight status...,please check later")
    
    
    f = Flight("CA980")
    f.flight_status
    
    航班查询
    

     现在定义好了类,那就实例化看下:

    f = Flight("CA980")
    
    f.flight_status
    
    f.flight_status =  2
    
    ---------输出:-------------------
    
    checking flight CA980 status 
    
    flight is arrived...
    
    Traceback (most recent call last):
    
      File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 58, in <module>
    
        f.flight_status =  2
    
    AttributeError: can't set attribute
    

     报错了,说不能更改属性值,那怎么办呢?可以通过@proerty.setter装饰器在装饰一下,需要写个新方法:

    class Flight(object):
        def __init__(self,name):
            self.flight_name = name
    
    
        def checking_status(self):
            print("checking flight %s status " % self.flight_name)
            return  1
    
    
        @property
        def flight_status(self):
            status = self.checking_status()
            if status == 0 :
                print("flight got canceled...")
            elif status == 1 :
                print("flight is arrived...")
            elif status == 2:
                print("flight has departured already...")
            else:
                print("cannot confirm the flight status...,please check later")
        
        @flight_status.setter #修改
        def flight_status(self,status):
            status_dic = {
    : "canceled",
    :"arrived",
    : "departured"
            }
            print("33[31;1mHas changed the flight status to 33[0m",status_dic.get(status) )
    
        @flight_status.deleter  #删除
        def flight_status(self):
            print("status got removed...")
    
    f = Flight("CA980")
    f.flight_status
    f.flight_status =  2 #触发@flight_status.setter 
    del f.flight_status #触发@flight_status.deleter
    

     上面还写了一个@flight_status.deleter,是允许可以将这个属性删除

    类的特殊成员方法:

    1.__doc__ 表示类的描述信息:

    class Foo:
    
        """ 描述类信息,这是用于看片的神奇 """
        def func(self):
            pass 
    print Foo.__doc__
    
    #输出:类的描述信息
    

    2.__module__和__class__

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

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

    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__构造方法

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

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

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

    Foo:
    
        def __init__(self):
            pass
    
        def __call__(self, *args, **kwargs):
    
            print '__call__'
    
     
    obj = Foo() # 执行 __init__
    
    obj()       # 执行 __call__
    

    6.__dict__查看类或对象中的所有成员

    class Province:
    
        country = 'China'
    
        def __init__(self, name, count):
            self.name = name
            self.count = count
    
        def func(self, *args, **kwargs):
            print 'func'
    
     
    # 获取类的成员,即:静态字段、方法、
    print Province.__dict__
    # 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
    
     
    obj1 = Province('HeBei',10000)
    print obj1.__dict__
    # 获取 对象obj1 的成员
    # 输出:{'count': 10000, 'name': 'HeBei'}
    
     
    obj2 = Province('HeNan', 3888)
    print obj2.__dict__
    # 获取 对象obj1 的成员
    # 输出:{'count': 3888, 'name': 'HeNan'}
    

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

    class Foo:
    
        def __str__(self):
            return 'alex li'
    
     
    obj = Foo()
    print obj
    # 输出:alex li
    

     8.__getitem__,__setitem__,__delitem__

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

    class Foo(object):
    
        def __getitem__(self, key):
            print('__getitem__',key)
    
        def __setitem__(self, key, value):
            print('__setitem__',key,value)
    
        def __delitem__(self, key):
            print('__delitem__',key)
    
    
    obj = Foo()
    result = obj['k1']      # 自动触发执行 __getitem__
    obj['k2'] = 'alex'   # 自动触发执行 __setitem__
    del obj['k1'] 
    

     9.__new__\__metaclass__

    class Foo(object):
    
        def __init__(self,name):
            self.name = name
    
    f = Foo("alex")
    

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

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

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

    所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

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

    a). 普通方式

    class Foo(object):
    
        def func(self):
            print('hello alex')
    

     b). 特殊方式

    def func(self):
        print 'hello wupeiqi'
    
    Foo = type('Foo',(object,), {'func': func})
    #type第一个参数:类名
    #type第二个参数:当前类的基类
    #type第三个参数:类的成员
    
    def func(self):
        print("hello %s"%self.name)
    
    def __init__(self,name,age):
        self.name = name
        self.age = age
    Foo = type('Foo',(object,),{'func':func,'__init__':__init__})
    
    f = Foo("jack",22)
    f.func()
    
    加上构造方法
    

    So ,孩子记住,类 是由 type 类实例化产生

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

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

    #_*_coding:utf-8_*_
    
    class MyType(type):
        def __init__(self, child_cls, bases=None, dict=None):
            print("--MyType init---", child_cls,bases,dict)
            #super(MyType, self).__init__(child_cls, bases, dict)
        
        # def __new__(cls, *args, **kwargs):
        #     print("in mytype new:",cls,args,kwargs)
        #     type.__new__(cls)
        def __call__(self, *args, **kwargs):
            print("in mytype call:", self,args,kwargs)
            obj = self.__new__(self,args,kwargs)
    
            self.__init__(obj,*args,**kwargs)
    
    class Foo(object,metaclass=MyType): #in python3
        #__metaclass__ = MyType #in python2
    
        def __init__(self, name):
            self.name = name
            print("Foo ---init__")
    
        def __new__(cls, *args, **kwargs):
            print("Foo --new--")
            return object.__new__(cls)
    
        def __call__(self, *args, **kwargs):
            print("Foo --call--",args,kwargs)
    # 第一阶段:解释器从上到下执行代码创建Foo类
    # 第二阶段:通过Foo类创建obj对象
    obj = Foo("Alex")
    #print(obj.name)
    
    自定义元类
    

     类的生成 调用 顺序依次是 __new__ --> __call__ --> __init__

     metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好

    反射:

    通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法

    def getattr(object, name, default=None): # known special case of getattr
        """
        getattr(object, name[, default]) -> value
        
        Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
        When a default argument is given, it is returned when the attribute doesn't
        exist; without it, an exception is raised in that case.
        """
        pass
    
    getattr(object, name, default=None)
    

     判断object中有没有一个name字符串对应的方法或属性

    def setattr(x, y, v): # real signature unknown; restored from __doc__
        """
        Sets the named attribute on the given object to the specified value.
        
        setattr(x, 'y', v) is equivalent to ``x.y = v''
    
    def delattr(x, y): # real signature unknown; restored from __doc__
        """
        Deletes the named attribute from the given object.
        
        delattr(x, 'y') is equivalent to ``del x.y''
        """
    
    delattr(x, y)
    
    class Foo(object):
     
        def __init__(self):
            self.name = 'wupeiqi'
     
        def func(self):
            return 'func'
     
    obj = Foo()
     
    # #### 检查是否含有成员 ####
    hasattr(obj, 'name')
    hasattr(obj, 'func')
     
    # #### 获取成员 ####
    getattr(obj, 'name')
    getattr(obj, 'func')
     
    # #### 设置成员 ####
    setattr(obj, 'age', 18)
    setattr(obj, 'show', lambda num: num + 1)
     
    # #### 删除成员 ####
    delattr(obj, 'name')
    delattr(obj, 'func')
    
    反射代码示例
    

     

    import importlib
    
    __import__('import_lib.metaclass') #这是解释器自己内部用的
    
    #importlib.import_module('import_lib.metaclass') #与上面这句效果一样,官方建议用这个 
    

    异常处理

    #异常:
    	try:
    	code
    	except (Error1,Error2)as e:
    		print e
    	
    	except Exception #抓住所有错误,一般不建议用
    
    #捕获字典错误
    data = {}
    try:
        data['name']
    except KeyError as e:
        print("没有这个KEY",e)
    
    #捕获列表错误
    names = ['tim','alex']
    try:
        names[3]
    except IndexError as e:
        print("没有这个索引值!",e)
    	
    #合起来
    data = {}
    names = ['tim','alex']
    try:
        names[3]
        data['name']
    except KeyError as e:
        print("没有这个key",e)
    except IndexError as e:
        print("列表操作错误",e)
    
    #当两种错误出现时,都采用同一处理办法时,可以这么写
    data = {}
    names = ['tim','alex']
    try:
        names[3]
        data['name']
    except (KeyError,IndexError) as e:
        print("没有这个key",e)
    
    
    #抓所有错误:
    data = {}
    names = ['tim','alex']
    try:
        #names[3]
        #data['name']
        open('tes.txt')
    except Exception as e:
        print("出错了",e)
    	
    #自定义异常
    class TimException(Exception):  #定义一个异常,继承基类Exception
        def __init__(self,msg):
            self.message = msg
    
        def __str__(self):
            return self.message
    
    try:
        raise TimException("数据库连不上")
    except TimException as e:
        print(e)
    

    Socket 编程

    参考:http://www.cnblogs.com/wupeiqi/articles/5040823.html

  • 相关阅读:
    vue+iview简单实现获取要上传文件的Base64字符串
    com.microsoft.sqlserver.jdbc.SQLServerException: 必须执行该语句才能获得结果。
    Java入门2.1---面向对象的主线1---类及类的构成成分:属性、方法、构造器、代码块、内部类
    淘系自研前端研发工具 AppWorks 正式发布
    百度开源一款前端图片合成工具库:MI
    微软体验超棒的Fluent UI宣传短片,爱了爱了
    oracle的购买价格研究
    .NET Core 网络数据采集 -- 使用AngleSharp做html解析
    【译】Google Markdown书写风格指南
    我终于逃离了Node(你也能)
  • 原文地址:https://www.cnblogs.com/guqing/p/6349054.html
Copyright © 2011-2022 走看看