静态方法

截断了类和方法的内在联系。 只是名义上归类管理,实际上在静态方法里访问不了类或者实例中的任何属性。

class Dog(object):

    def __init__(self, name):
        self.name = name

    @staticmethod    # 静态方法截断了类和方法的联系。 和在类外设置函数是一样的。
    def eat(self):
        print('%s is earting bum ' %(self.name))

d = Dog("Rory")
d.eat()

返回错误结果如下:

Traceback (most recent call last):
  File "/Users/PycharmProjects/learningnote/moduel3/OPP进阶 - 静态方法.py", line 18, in <module>
    d.eat()
TypeError: eat() missing 1 required positional argument: 'self'

类方法

只能访问类变量,不能访问实例变量。

class Dog(object):

    name = "marlynda"

    def __init__(self, name):
        self.name = name

    @classmethod  # 类方法
    def eat(self):
        print('%s is earting bum' % self.name)

d = Dog("Rory")
d.eat()  # 在类方法下, 调用的self.name是类变量

返回结果:

marlynda is earting bum

属性方法

@property 将一个方法变成一个静态属性,即调用是不用加()

class Dog(object):

    name = "marlynda"

    def __init__(self, name):
        self.name = name

    @property
    def eat(self):
        print('%s is earting bum' % self.name)

d = Dog("Rory")
d.eat

当该方法原来有参数时,改写方式应该如下:

class Dog(object):

    name = "marlynda"

    def __init__(self, name):
        self.name = name
        self.__food = None   # 3. 添加私有属性__food

    @property          # 1. 设置属性方法,将方法转变为静态属性
    def eat(self):
        print('%s is eating %s' % (self.name, self.__food))

    @eat.setter        # 2. 另增加一个同为eat的方法,并增加参数food
    def eat(self, food):
        print("set the food:", food)
        self.__food = food    # 4. 传入参数,更新私有属性__food

    @eat.deleter       # 5. 作为属性, 单纯调用 del d.eat,是删不掉。需要再写个@eat.deleter
    def eat(self):
        del self.__food
        print("删完了")

d = Dog("Rory")

d.eat
d.eat = "bum"
d.eat
d.eat = "beef"
d.eat

del d.eat

返回结果

Rory is eating None
set the food: bum
Rory is eating bum
set the food: beef
Rory is eating beef
删完了

属性方法在实际情况中,比较有用。很多场景中是不能简单通过定义静态属性来实现的。

比如,类似像飞常准这样的平台,获取一个航班的当前状态(到达,延迟,取消,还是飞走等), 需要经历以下几步:

  1. 链接航空公司提供的API接口:可能是json, xml等
  2. 对查询结果进行解析
  3. 返回结果给你的用户

获取这些status其实是一系列动作的结果,但是客户不关心,他们只需要这系列动作后的结果即可。

class Fight(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 cancelled...')
        elif status == 1:
            print("flight has 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):
        print("flight %s has change status to %s" %(self.flight_name, status))

f = Fight("CA980")
f.flight_status
f.flight_status = "2"
f.flight_status

返回信息

checking flight CA980 status
flight has arrived...
flight CA980 has change status to 2
checking flight CA980 status
flight has arrived...

特殊成员方法

特殊方法一般主要实现模拟标准类型重载操作符

1. __doc__

现实类的描述信息, 调用如下 print(Foo.__doc__)

2. __module__ __class__

__module__ 表示当前操作的对象在哪个模块 __class__ 表示当前操作的对象的类是啥么

3. __init__

4. __del__

5. __bases__

显示其父类的集合的元祖

5. __call__

对象后面加括号,促发执行,即对象() 或者 类()()。比较重要

class Foo:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        print
        '__call__'


obj = Foo()  # 执行 __init__
obj()  # 执行 __call__

6. __dict__

查看类或者对象中的所有成员

class Dog(object):

    def __init__(self, name):
        self.name = name

    def eat(self):
        print('%s is earting bum ' %(self.name))

d = Dog("Rory")

print(Dog.__dict__)  # 打印类里的所有属性,不包括实例属性
# 返回:{'__module__': '__main__', '__init__': <function Dog.__init__ at 0x103121840>, 'eat': <function Dog.eat at 0x1031218c8>, '__dict__': <attribute '__dict__' of 'Dog' objects>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': None}
print(d.__dict__)    # 打印所有实例属性,不包括类属性
# 返回:{'name': 'Rory'}

7. __str__

如果一个类中定义了__str__方法, 那么打印对象时,默认输出该方法的返回值。 不打__str__的话,会返回内存地址。 django中用的比较多。

class Dog(object):

    def __init__(self, name):
        self.name = name

    def eat(self):
        print('%s is earting bum ' %(self.name))

    def __str__(self):
        return "<obj: %s>" % self.name

8. __getitem__, __setitem__, __delitem__

用于索引操作,如字典,以上分别表示获取、设置、删除数据。多数情况用不到。 在封装一个底层的时候,经常会用到,让客户以为在调用一个字典。

class Foo(object):

    def __init__(self, ):
        self.data = {}

    def __getitem__(self, key):
        print('__getitem__', key)
        return self.data.get(key)

    def __setitem__(self, key, value):
        print("__setitem__", key, value)
        self.data[key] = value


    def __delitem__(self, key):
        print("__delitem__", key)


obj = Foo()
obj['name'] = 'alex'
print(obj.data)
del obj["name"]

9. __new__ 和 __metaclass__

先来看段代码, 一般我们普通方式创建类如下:

class Foo(object):

    def __init__(self,name):
        self.name = name

f = Foo("moo")

print(type(f))    # 表示:obj对象由Foo类创建得来, f是Foo的一个实例
# 返回:<class '__main__.Foo'>
print(type(Foo))   # 表示:Foo类由type类创建得来,Foo是type的一个实例
# 返回:<class 'type'>

这里就引出了第2种创建类的方法,乃装逼利器,即特殊方式。其基本原理(以以上例子为列), f是Foo类创建的,是Foo的一个实例。在python中,一切皆对象。其实Foo类本身也是一个实例,是type类所创建的一个实例。 特殊方式创建类的方式如下:

def func(self):
    print('hello, 特殊方法')

def __init__(self, name, age):
    self.name = name
    self.age = age

Moo = type("Moo", (object,), {'talk': func,
                              '__init__': __init__})
# type第一参数:类名
# type第二参数:当前类的基类
# type第三参数:类的成员

m = Moo("alex", "22")
m.talk()

多数情况不大用到,重点是内部逻辑,以及“一切皆对象”的概念。

类的创建过程(很难理解)

类中有个属性__metaclass__, 表示该类是由谁来实例化创建的。

__init__相比,__new__更像一个正真的构造器。因为__new__()必须返回一个合法的实例,这样调用__init__()时,就可以把这个实例作为self传给它。__init__()更像解释器创建一个实例后调用的第一个方法。

10. 其他

详见《python核心编程v2》平67-369

类、实例和其他对象的内建函数

1. issubclass(sub, sup)

布尔函数判断一个类是另外一个类的子类或者孙类。 从2.2开始,sup可能是一个父类的集合的元祖。

2. isinstance(obj1, obj2)

布尔函数判断一个对象是否是另外一个给定类的实例,非常有用。 obj2 是给定类。

3. *attr系列函数 hasattr(), getattr(), setattr(),delattr()

重要,详见4.反射

4. dir(obj=None)

dir()作用在不通对象,内容不同

  1. 实例:显示实例变量,实例所在的类及所有它的基类中定义的方法及类属性
  2. 类:显示类以及他的所有基类的__dict__的内容。 但它不显示定义在元类metaclass 中的类属性
  3. 模块:显示模块的__dict__的内容
  4. 不带参数:显示调用者的局部变量

5. super(type, obj=None)

方便的找到所有的父类(不需要给出父类的名称),并调用其相关属性。 而不是一个个采用非绑定方式调用父类方法。

6. var(obj=None)

var()dir()类似。区别在于给定参数必须有一个__dict__属性。 如果返回不了一个key和value的形式,会出现TypeError异常。

 

 

posted on 2018-01-09 21:53  lg100_lg100  阅读(160)  评论(0编辑  收藏  举报