Python说文解字_杂谈05

1. isinstance和type:

  is和==符号,is指的是内存地址,是不是一个对象,ID知否相同

  集成链

class A:
    pass

class B(A):
    pass

b = B()
print(isinstance(b,B))
print(isinstance(b,A))

print(type(b) is B)
print(id(type(b)),id(B))
# 2943616512536 2943616512536

2. 类变量和对象变量:

  类中的self == 实例,其实就等于a = A()的a,等于传递进去,这就是为什么类中有self的原因。

class A:
    aa = 1
    def __init__(self,x,y):
        self.x = x
        self.y = y


a = A(2,3)
A.aa = 11
a.aa = 100
print(a.x,a.y,a.aa)
# 2 3 1
print(A.aa)
# print(A.x,A.y) # 抛异常

# 2 3 100
# 11

  记住:查找的顺序是由下而上进行查找

  记住:类变量只能通过类来更改,如果通过实例去更改,只会开辟一块儿新的变量,类的变量其实不能更改,但是看起来是一个变量。类的变量是所有成员共享的。

3. 类属性和实例属性的查找顺序:

  定义在内部的实例或者方法。

  查找分深度查找和广度查找,其实前面有类名.__init__这样继承父类的方式就是深度查找,我们Py3用的是MRO算法,用的是C3,super()就是一种C3的查找方法。

class A:
    name = "A"
    def __init__(self):
        self.name = "obj"

a = A()
print(a.name)
# 会打印obj回不到name变量

  

class D:
    pass

class C(D):
    pass

class B(D):
    pass

class A(B,C):
    pass

print(A.__mro__)
# (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>)

  记住:可以用__MRO__查看继承链的关系。

  记住:py2,必须要写object才有object,py3.不用写也会继承object,是一种新式类

4. 静态方法、类方法、对象方法(实例方法):

class Date:
    # 构造函数
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    def tomoroow(self):
        self.day += 1

    @staticmethod
    def parse_from_string(date_str):
        year, month, day = tuple(date_str.split("-"))
        return Date(int(year),int(month),int(day))

    @staticmethod
    def valid_str(date_str):
        year, month, day = tuple(date_str.split("-"))
        if int(year)>0 and (int(month)>0 and int(month)<12) and (int(day)>0 and int(day)<=31):
            return True
        else:
            return False

    @classmethod
    def from_string(cls,date_str):
        year, month, day = tuple(date_str.split("-"))
        return cls(int(year),int(month),int(day))

    def __str__(self):
        return "{year}/{month}/{day}".format(year=self.year,month=self.month,day=self.day)

if __name__ == '__main__':
    new_day = Date(2019,6,7)
    new_day.tomoroow()
    print(new_day)

    #2019-6-7
    # date_str = "2019-6-7"
    # year,month,day = date_str.split("-")
    # print(year,month,day)

    #用staticmethod完成初始化
    date_str = "2019-6-7"
    new_day = Date.parse_from_string(date_str)
    print(new_day)

    # 用staticmethod完成初始化
    date_str = "2019-6-7"
    new_day = Date.from_string(date_str)
    print(new_day)

    print(Date.valid_str(date_str))

  记住:类中有属性和方法,前面我们说了属性分:类属性,对象属性(实例属性),还有一种静态属性。在方法这个层面也分:类方法、静态方法和对象方法(实例方法)。

  记住:对象方法平时用的很多,记住在类中的self就是用于传回实例的那个标签的。

  记住:静态方法和类方法相同点就是可以直接通过类来进行访问,不用再实例化。 不同点是:如果返回值是类名的话,静态方法每次都要更改return 类名,而类方法不用。

  记住:静态方法@staticmethod,中的是self。类方法@staticclass,中的是cls。这两种其实就是和什么关联。

 5. 数据封装和私有属性:

class User:
    def __init__(self,birthday):
        self.__birthday = birthday

    def get_age(self):
        return 2019 - self.__birthday

class Student(User):
    def __init__(self,birthday):
        self.__birthday = birthday

if __name__ == '__main__':
    user = User(1981)
    print(user.get_age())
    # print(user.__birthday) # 不能访问
    print(dir(user))
    # ['_User__birthday',
    print(user._User__birthday)
    print(user._Student__birthday)

  记住:私有属性在Py中突破的比较简单一些,不用通过反射机制。

  记住:私有属性其实就是在类中创建了一个_类名.__私有属性的变量而已。我们可以通过dir看到这个变量。而且可以直接拿到那个私有属性。

6. Py的自省:

  通过一定的机制查询到对象的内部结构。

class Person:
    """
"""
    name = "user"

class Student(Person):
    def __init__(self,school_name):
        self.school_name = school_name

if __name__ == '__main__':
    user = Student("Oxford")

    # 通过__dict__查询属性。
    print(user.__dict__)
    # {'school_name': 'Oxford'}
    print(user.name)
    # user
    print(Person.__dict__)

    user.__dict__["schoole_addr"] = "北京"
    print(user.__dict__)
    # {'school_name': 'Oxford', 'schoole_addr': '北京'}

    print(dir(user))

   记住:查看类中的属性的两个魔法函数是__dict__和dir,其中dict是一种高效的数据存储方式。用dir可以查看全部的。

  记住:__doc__是查看类中的文档注释内容的。

7. super函数:

  实际上就是调用我们的父类。

class A:
    def __init__(self):
        print("A")

class B(A):
    def __init__(self):
        print("B")
        # super(B,self).__init__() #这是Py2的用法
        super().__init__() # 这是Py3的用法。

# 既然重写了B的构造函数,为什么还要去调用super
# super到底执行顺序是什么样的?

if __name__ == '__main__':
    b = B()

  记住:查找顺序就是MRO

  记住:Py2的调用方法和Py3的调用方法不同,但是Py3也可以用Py2的格式。

8. 类的调用关系:

  mixin模式(属于Python几大设计模式中的一个,后面说)

  minin类功能单一

  不和基类管理啊,可以和任意基类组合,基类可以不和mixin关联就能初始化成功

  在mixin中不要使用super之中用法。

9. 上下文管理器with和contextlib

def exe_try():
    try:
        # f_read = open("bobby.txt")
        print("code started")
        # f_read.close()
        raise KeyError
        return 1
    except KeyError as e:
        print("key error")
        return 2
    else:
        print("other error")
        return 3
    finally:
        print("finally")
        return 4


if __name__ == '__main__':
    result = exe_try()
    print(result)
    # 如果有finally语句会return 4,如果没有finally的话,执行try和Except语句,返回2

  上下文管理器协议(是协议就要和魔法函数挂钩)

  因此涉及到了__enter__和__exit__

# 上下文管理器协议
class Sample:
    def __enter__(self):
        print("enter")
        return self
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")
    def __str__(self):
        return "this is finally?"
    def do_something(self):
        print("do something")
with Sample() as sample:
    sample.do_something()
    print(sample)

  记住:上下文管理器,其实就是规定类的进和出的关系。比如我们用with open as f:这样的管理方式,就是在open当中规定了__enter__和__exit__两个魔法函数。进出关系,所以不用关闭了。

  记住:__exit__指的是最后的退出,因此里面要打印字符串打印的__str__是在这个之前的。

  import contextlib

import contextlib

@contextlib.contextmanager
def file_open(filename):
    print("file open")  # __enter__
    yield {}
    print("file close") # __exit__


with file_open("bobby.txt") as f_opened:
    print("file processing")
    
# file open
# file processing
# file close

  记住:上下文管理器函是一个用装饰器的方式生成一个上下文管理器,巧妙的运行了生成器的特性。yield的方式。

  

  

原文地址:https://www.cnblogs.com/noah0532/p/10987522.html