No.21特殊成员&异常处理

No.21

今日概要

  • 嵌套
  • 特殊成员:__init__
  • type / isinstance / issubclass / super
  • 异常处理

内容回顾

def login():
    pass
login()
class Account:
    def login(self):
        pass
obj = Account()
obj.login()
  1. 谈谈你了解的面向对象?

    • 封装
    • 继承
    • 多态
  2. 类和对象是什么关系?

    • 对象是类的一个实例

      class Foo:
          def __init__(self, name):
              self.name = name
          def run(self)
          	pass
          
      obj1 = Foo('alex')
      obj2 = Foo('eric')       
      
  3. self 是什么?

    • 本质就是一个形式参数

      # self就是一个形式参数,对象调用方法是,Python内部会将对象传给这个参数。
      class Foo:
          def run(self, num): # num形参需要自己传实参
              pass
          
      obj = Foo()
      obj.run(5)
      
  4. 类成员 & 对象成员 以及它们之间的关系

    class Foo:
        name = 'alex'
        def run(self):
            pass
        
    obj = Foo()
    
  5. 类 / 对象 / 方法 都可以当作变量或嵌套到其它类型中。

    class Foo:
        def run(self):
            pass
        
    v = [Foo, Foo]
    v = [Foo(), Foo()]
    obj = Foo()
    v = [obj.run, obj.run]
    
    class School(object):
        def __init__(self, title):
            self.title = title
            
    class Course(object):
        def __init__(self, name, school_obj)
        	self.name = name
        	self.school_obj = school_obj
       
    class Classes(object):
        def __init__(self, cname, course_obj)
        	self.cname = cname
        	self.course_obj = course_obj
        	
    s1 = School('北京')
    
    c1 = Course('Python', s1)
    c2 = COurse('Go', s1)
    
    cl1 = Classes('全栈1期', c1)
    
    
    # 方法在定义的时候,一般情况下是对类的对象做操作或做处理的。
    class School(object):
        def __init__(self, title):
            self.title = title
        def rename(self):  # 学校改名
            pass
            
    class Course(object):
        def __init__(self, name, school_obj)
        	self.name = name
        	self.school_obj = school_obj
        def reset_price(self): # 课程改价
        	pass
       
    class Classes(object):
        def __init__(self, cname, course_obj)
        	self.cname = cname
        	self.course_obj = course_obj
        def shangke(self): # 班级上课
        	pass
        	
    s1 = School('北京')
    
    c1 = Course('Python', s1)
    c2 = COurse('Go', s1)
    
    cl1 = Classes('全栈1期', c1)
    

内容详细

1.嵌套

  • 函数:参数可以是任意类型。
  • 字典:类和对象都可以做字典的key和value
  • 继承的查找关系
class StarkConfig(object):
    pass

class AdminSite(object):
    def __init__(self):
        self.data_list = []

    def register(self, arg):
        self.data_list.append(arg)

site = AdminSite()
obj = StarkConfig()

site.register(obj)
class StarkConfig(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

class AdminSite(object):
    def __init__(self):
        self.data_list = []
        self.sk = None

    def set_sk(self, arg):
        self.sk = arg

site = AdminSite()  # data_list = [] sk = None
site.set_sk(StarkConfig)    # sk = StarkConfig
site.sk('alex', 18)
class StarkConfig(object):
    pass

class Foo(object):
    pass

class Base(object):
    pass

class AdminSite(object):
    def __init__(self):
        self._register = {}

    def registry(self, key, arg):
        self._register[key] = arg


site = AdminSite()
site.registry(1, StarkConfig)
site.registry(2, StarkConfig)
site.registry(3, StarkConfig)
site.registry(4, Foo)
site.registry(5, Base)

for k, v in site._register.items():
    print(k, v())
class StackConfig(object):
    pass

class UserConfig(StackConfig):
    pass

class AdminSite(object):
    def __init__(self):
        self._register = {}

    def registry(self, key, arg=StackConfig):
        self._register[key] = arg

    def run(self):
        for key, value in self._register.items():
            obj = value()
            print(key, obj)

site = AdminSite()
site.registry(1)
site.registry(2, StackConfig)
site.registry(3, UserConfig)
site.run()
class StackConfig(object):
    list_display = '666'

class UserConfig(StackConfig):
    list_display = '888'

class AdminSite(object):
    def __init__(self):
        self._register = {}

    def registry(self, key, arg=StackConfig):
        self._register[key] = arg

    def run(self):
        for key, value in self._register.items():
            obj = value()
            print(key, obj.list_display)

site = AdminSite()
site.registry(1)
site.registry(2, StackConfig)
site.registry(3, UserConfig)
site.run()
class StackConfig(object):
    list_display = '666'

    def changelist_view(self):
        print(self.list_display)

class UserConfig(StackConfig):
    list_display = '888'

class AdminSite(object):
    def __init__(self):
        self._register = {}

    def registry(self, key, arg=StackConfig):
        self._register[key] = arg

    def run(self):
        for key, value in self._register.items():
            obj = value()
            obj.changelist_view()

site = AdminSite()
site.registry(1)
site.registry(2, StackConfig)
site.registry(3, UserConfig)
site.run()

2.特殊成员

2.1__init__

class Foo:
    '''
    对类注释
    '''
    def __init__(self, a1):
            '''
            初始化方法
            '''
            self.a1 = a1

obj = Foo('alex')

2.2__new__

# Python中当类实例化对象时,会先执行类中的new方法,再执行init方法。
# Python会使我们创建类默认继承object类,所以我们在创建的类中即使不写new方法,当实例化对象时我们创建的类会调用object类中的new方法来创建空的对象,在执行我们创建类中的init方法给空的对象中赋值。
class Foo(object):
    def __init__(self, a1):
        '''
        用于给对象中赋值(初始化方法)
        '''
        print('给对象中进行赋值')
        self.a1 = a1

    def __new__(cls, *args, **kwargs):
        '''
        用于创建空的对象(构造方法)
        '''
        print('创建对象')
        return object.__new__(cls) # return返回什什么对象就是什么
    				
obj = Foo()

# 默认new方法返回的是一个空的内存地址给对象,所以init方法才能在空地址中赋值。如果我们在类中让new返回123,那么创建的对象就是123,init方法就没有办法给对象赋值(此时对象不是一个空的内存地址)。

2.3__call__

# 对象后面加括号会执行call方法
class Foo:
    def __call__(self, *args, **kwargs):
        print('执行call方法')

obj = Foo()
obj()
Foo()()

2.4get / set / del

__getitem__ __setitem__ __delitem__

class Foo(object):
    def __setitem__(self, key, value):
        print(key,value)
    def __getitem__(self, item):
        return item+'加油'
    def __delitem__(self, key):
        pass

obj1 = Foo()
obj1[666] = 888       # 此语法会让对象自动调用类中__setitem__方法
val = obj1['中国']	# 此语法会让对象自动调用类中__getitem__方法
print(val)
del obj1['alex']      # 此语法会让对象自动调用类中__delitem__方法

2.5__str__

class Foo(object):
    def __str__(self):
        '''
        只有在打印对象时,会自动调用此方法,并将返回值在页面显示出来。
        '''
       return 11
    
obj = Foo()     
print(obj, type(obj))
class User(object):
    def __init__(self, name, email):
        self.name = name
        self.email = email

    def __str__(self):
        return '%s %s'%(self.name, self.email)

user_list = [User('张三', '123@qq.com'), User('李四', '456@qq.com')]

for item in user_list:
    # print(item.name, item.email)
    print(item)

2.6__dict__

class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

obj = Foo('alex', '18')
print(obj)
print(obj.name)
print(obj.age)
val = obj.__dict__ # 去对象中找到所有变量,并将其转换为字典
print(val)

2.7上下文管理 (面试题)

class Foo(object):
    def __enter__(self):
        self.a = open('test.txt', 'a', encoding='utf-8')
        return self.a # 返回什么as后面的变量就是什么
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.a.close()
# 此语法会执行对象中的enter方法,然后返回值给as后面的变量
with Foo() as f:
    f.write('alex')
    f.write('alex')
    f.write('alex')
# 面试题:添加代码使下面代码能实现。
'''
class Context:
	pass
with Context() as ctx:
	ctx.do_something()
'''
        
class Context:
    def __enter__(self):
        print('进入')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('退出')

    def do_something(self):
        print('内部执行')


with Context() as ctx:
    ctx.do_something()

2.8对象相加 (面试题)

#加减乘除都有对应的方法
class Foo(object):
    def __add__(self, other):
        return 123 # 返回什么val就是什么

obj1 = Foo()
obj2 = Foo()
val = obj1 + obj2  # 会调用add方法,obj1传给self,obj2传给other

特殊成员:就是为了能够快速实现执行某些方法而生。

3.内置函数补充

3.1 type()

# 查看类型
class Foo():
    pass

obj = Foo()
if type(obj) == Foo:
    print('obj是Foo的对象')

3.2 issubclass()

# 判断第一个类是不是第二个类的继承类(会考虑多继承)
class Base:
    pass
class Show(Base):
    pass
class Foo(Show):
    pass
class Bar:
    pass

print(issubclass(Bar, Base))  # False
print(issubclass(Foo, Base))  # True 虽然Foo不是Base的直接继承类但是是Base多继承类。

3.3 isinstance()

# 判断对象是否是某个类的或其继承类的实例
class Base(object):
    pass
class Foo(object):
    pass
class Bar(Base):
    pass

obj = Bar()
print(isinstance(obj, Foo))  # False
print(isinstance(obj, Bar))  # True
print(isinstance(obj, Base)) # True
'''
type() 不考虑继承关系。
isinstance() 考虑继承关系。
'''

4.super函数


class Base(object):
    def func(self):
        print('base.func')
        return 666

class Foo(Base):
    def func(self):
        result = super().func()
        print('foo.func')
        print(result)
    
obj = Foo()
obj.func() 
# super().func() 根据self对象所属类的继承关系,按继承顺序往下继续找同名方法并执行。(只要找到一个就不再找了)
class Bar(object):
    def func(self):
        print('bar.func')
        return 888

class Base(Bar):
    pass

class Foo(Base):
    def func(self):
        result = super().func()
        print('foo.func')
        print(result)

obj = Foo()
obj.func()
# super().func() 根据self对象所属类的继承关系,按继承顺序往下继续找同名方法并执行。(只要找到一个就不再找了)
class Base(object): 
    def func(self):
        super().func()
        print('foo.func')

class Bar(object):
    def func(self):
        print('bar.func')

class Foo(Base,Bar): # Foo → Base → Bar
    pass

obj1 = Foo()
obj1.func()

obj2 = Base()
obj2.func()  # 报错

# super().func() 根据self对象所属类的继承关系,按继承顺序往下继续找同名方法并执行。(只要找到一个就不再找了)

5.异常处理

5.1基本格式

try:
    pass
except Exception as e:
    pass
# 全部捕获
try:
    # int('alex')
    v = []
    v[100]
except Exception as e:
    print(e)  # e是Exception类的对象,对象中有一个错误信息。
    
'''
int('alex') # ValueError

v = []
v[100] # IndexError
'''

# 可以捕获
try:
    int('alex')
except ValueError as e:
    print(e)

# 捕获不到
try:
    v = []
    v[100]
except ValueError as e:
    print(e)

try:
    v = []
    v[100]
except ValueError as e:
    print(e)
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
try:
    v = []
    v[100]
except ValueError as e:
    print(e)
except IndexError as e:
    print(e)
except Exception as e:
    print(e)
finally:   # 无论对错都会执行
    print('最后')
def func():
    try:
        v = 1
        return 123
    except Exception as e:
        print(e)
    finally:     # 特殊:即使放在函数,遇到return也会执行。
        print('最后')

func()

5.2主动触发异常

try:
    int('666')
    raise Exception(888)  # 代码中主动抛出异常
except Exception as e:
    print(e)   # 结果888
# 写一个函数,判断alex是否在文件中。
def func():
    result = True
    try:
        with open('test.txt','r',encoding='utf-8') as f:
            data = f.read()
        if 'alex' not in data:
            raise Exception()
    except Exception as e:
        result = False
    return result

5.3自定义异常

class MyException(Exception):
	def __init__(self, message):
        super().__init__()
        self.message = message
      
try:
    raise MyException('alex')
except MyException as e:
    print(e.message)

总结

  • 特殊成员 ▲
  • 嵌套
  • type / issubclass / isinstance()
  • super
  • 异常
posted @ 2020-03-19 15:31  Sco_Lunatic  阅读(86)  评论(0)    收藏  举报