搬马

导航

 

一、成员修饰符

  共有成员

  私有成员,__字段名,__方法

    - 无法直接访问,只能间接访问

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.__age = age    #字段名前加双下划线就成私有成员了,外部无法直接访问

    def show(self):      #如果想访问的话需要定义一个公有成员,然后返回私有私有字段。
        return self.__age

obj = Foo('alex',18)
print(obj.name)
print(obj.__age)    #外部无法直接访问,AttributeError: 'Foo' object has no attribute '__age'
print(obj.show())   #通过定义的公有方法,可以间接访问

 

公有字段私有化

class Foo:
    __v = '123'   #静态字段
    def __init__(self):
        pass

    def show(self):
        return Foo.__v    #前面必须要加Foo

print(Foo.__v)  #静态字段私有之后也是无法通过外部访问的
obj = Foo()
print(obj.show())

 

继承中的私有字段:

class F():
    def __init__(self):
        self.ge = '123'
        self.__gene = '234'

class S(F):
    def __init__(self,name):
        self.name = name
        self.__age = 18
        super(S,self).__init__()    #想要使用父亲字段,必须要执行父类Init

    def show(self):
        print(self.name)
        print(self.__age)
        print(self.ge)    #必须要在init中同时执行父类,不然此代码报错:AttributeError: 'S' object has no attribute 'ge'
        print(self.__gene)    #继承的时候父亲中的私有字段不继承,如果想访问,要在父类中写一个公有方法间接访问

obj = S('alex')
obj.show()  #AttributeError: 'S' object has no attribute '_S__gene'

 

二、特殊成员

  __init__  类()自动执行

  __call__  对象()  类()()自动执行

class foo:

    def __init__(self):
        pass

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

foo()()     #对象加括号自动执行__call__方法

 

  __int__  int(对象)

class foo:
    def __init__(self):
        pass

    def __int__(self):
        print('1111')
        return 2222

obj = foo()
print(obj,type(obj))    #<__main__.foo object at 0x000000000065E3C8> <class '__main__.foo'>
r = int(obj)    #int一个对象,自动执行对象中的__int__方法,并将返回值赋值给int对象
print(r)    #2222

 

  __str__  str(对象)

class foo:
    def __init__(self):
        pass

    def __str__(self):
        return 'alex'

obj = foo()
print(obj,type(obj))    #数据类型为<class '__main__.foo'>
i = str(obj)    #str一个对象,自动执行对象中的__str__方法
print(i)    #alex

 

class foo:
    def __init__(self,n,a):    #TypeError: object() takes no parameters,如果出现这个错误,一般是init写成了int
        self.name = n
        self.age = a

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

obj = foo('alex',18)
print(obj)  #print(str(obj))   str(obj)运行对象中的__str__方法,并获取其返回值

  __add__

  __del__

class foo:
    def __init__(self,n,a):
        self.name = n
        self.age = a

    def __add__(self, other):   #self = obj1,other = obj2
        return 'xxxoooo'

    def __del__(self):
        print('析构方法')   #对象被销毁时,自动执行

obj1 = foo('alex',18)
obj2 = foo('eric',66)
r = obj1 + obj2     #两个对象相加时,自动执行第一个对象的__add__方法,并且将第二个对象当做参数传入
print(r,type(r))

 

  __dict__  #将对象中封装的所有内容以字典的形式返回

class foo:
    def __init__(self,n,a):
        self.name = n
        self.age = a
        self.gender = 'male'

obj = foo('alex',18)
d = obj.__dict__
print(d)    #{'gender': 'male', 'name': 'alex', 'age': 18}

ret = foo.__dict__    #不仅可以返回对象的,也可以返回类中的成员,包括类的注释
print(ret)

 

  __getitem__  #切片(sliceo类型)或者索引

  __setitem__  

  __delitem__

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

    def __getitem__(self, item):
        return item+10  #因为这是获取数值,所以有返回值,下面两个没必要有返回值,因为也没地方接收了

    def __setitem__(self, key, value):  #key其实就是索引
        print(key,value)

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

li = foo('alex',18)
r = li[8]   #自动执行li对象的类中的__getitem__方法,8当作参数传递给item
print(r)

li[100] = "asdjk"   #这种对象带[]的形式,将自动执行__setitem__方法,key为中括号中值,value为等号后面值
# 这个方法没必要有返回值,因为这已经是个等式了,有返回值也没地接收了

del li[999]   #这种形式和类中的__delitem__这个方法是对应的,执行此命令,将执行__delitem__方法

#只要前面几个的语法这样写,就对应执行上面的函数,也只是对应关系,具体执行什么操作和表面意思一点关系都没有

 

  __iter__

class Foo:

    def __iter__(self):
        return iter([11,22,33])

obj = Foo()

for i in obj:
    print(i)

# 如果对象中有__iter__方法,那么该对象就是可迭代对象。
# 可迭代对象.__iter__返回的是一个迭代器。
# for循环的时候,如果循环的对象是可迭代对象,那么先执行对象的__iter__,然后针对return的迭代器进行迭代。
# 如果循环的对象是迭代器,那么就直接进行迭代。
# 迭代的本质其实就是执行迭代器的next方法

 

metaclass元类

在python中一切皆对象,对象是对象,类也是对象,类是type的对象。

class Foo:
    def func(self):
        print(123)
# =============================================================================
def func(self):
    print("hello world!")

Foo = type("QQQ",(object,),{"func":func})   #声明一个类,类中有一个成员func,成员信息可以用__dict__查看

# 上面两种写法是一样的
obj = Foo()
print(Foo.__dict__)
obj.func()

 

 

异常处理

try:
    # 代码块,逻辑
    inp = input("请输入:")
    i = int(inp)
except Exception as e:
    # e是Exception的对象,对象中封装了错误信息
    # 上述代码块出错,自动执行当前代码块的内容
    print(e)
    i = 1

Exception是大BOSS,包含所有异常,如果想捕捉某一类型的异常可以用具体异常类型。

try:
    int("22w")
except IndexError as e:
    print(e)
except ValueError as e:
    print("value_error:",e)
except Exception as e:
    print("Exception",e)
else:
    print("没错的时候执行这块,有错时不执行")
finally:
    print("无论是否错误都执行")

 

反射:

  - getattr

  -setattr

  -hasattr

  -delattr

  通过字符串的形式操作对象中的成员

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

    def show(self):
        print('this is the test')

obj = foo('alex',18)

r = getattr(obj,'name')     #有返回值,返回值为对应字段的值
print(r)    #alex
r1 = getattr(obj,'show')    #引种形式获取成员,括号后面的参数必须是字符串
r1()    #执行show方法,得到结果:this is the test,说明getattr不仅可以获得字段,也可以获得方法。

setattr(obj,'score',88)   #没有返回值,返回值为None
print(obj.score)    #88

r2 = hasattr(obj,'gender')  #有返回值,返回值为布尔值
print(r2)   #False

delattr(obj,'score')
print(obj.score)    #AttributeError: 'foo' object has no attribute 'score'

 

#类也是对象,所以也可以对类使用上述函数
class foo:
    country = 'china'

    def show(self):
        print('this is the test')

r = getattr(foo,'country')    #同样可以获得里面的字段,因为类是type的对象,从这块可以看出,其实country和self.name一样,都是封装在对象里的内容
print(r)    #china

r1= hasattr(foo,'show')     #
print(r1)   #True
#为什么是ture?由此可以看出getattr获取的是包含在对象内部的内容。
# 那为什么之前对象可以获得类中的内容?因为对象中有类对象指针,所以类中的成员也是对象中的一部分

 

#在python中一切皆对象,所以模块也是对象,对模块也可以操作
import model1

r1 = getattr(model1,'s')
print(r1)
setattr(model1,'tel',88888)     #虽然设置了,可以获取到值,但这些现在只是存在内存中,并未存在文件中
print(getattr(model1,'tel'))

r2 = getattr(model1,'func')     #获取模块中的函数
r2()

r3 = getattr(model1,'cls')      #获取模块中的类
obj = r3('alex',18)     #创建对象
print(obj.name)     #获取类中的name字段

 

反射小练习:仿WEB业面点击获得相应信息

class foo:
    def f1(self):
        return '首页'
    def f2(self):
        return '新闻'
    def f3(self):
        return '精华'

inp = input('please input your URL>>>:')
obj = foo()
#因为方法中需要有self,所以要创建对象,如果不想创建对象,有两种方法,一是用静态方法,这样就不用传self了,另外一个是引入模块,在定义函数,这样也不用传参数
if hasattr(obj,inp):
    func = getattr(obj,inp)    #这里用Foo也可以取到方法,但是执行的时候需要self,解决方法如上
    result = func()
    print(result)
else:
    print('404')

 

 

单例模式:

单例,使用同一个实例(对象)

 

class foo:
    __v = None    #这个字段是静态字段,而且是私有字段
    @classmethod    #此处为类方法,这样的话,下面的方法的cls就不用传参了,python会自动传,此处也可以用静态方法,这样下面的参数就需要自己传了
    def get_instance(cls):     #此处的cls为类
        if cls.__v:
            return cls.__v
        else:
            cls.__v = foo()     #给__v赋值,前面必须要加cls,就像给self.name赋值一样
            return cls.__v      #return的值也要是cls.__v

obj = foo.get_instance()    #因为上面用的是类方法,所以这块不用传入参数类,如果为静态方法,那么此处括号内要加foo才行
obj1 = foo.get_instance()
obj2 = foo.get_instance()

print(obj)    #<__main__.foo object at 0x00000000009B70B8>
print(obj1)    #<__main__.foo object at 0x00000000009B70B8>
print(obj2)     #<__main__.foo object at 0x00000000009B70B8>

 

第二次写单例:

class Foo:
    __v = None

    @classmethod    # 这块用类方法好一些,因为在方法里面用到类了,用静态方法也行,只不过就要写成Foo.__v
    def get_instance(cls):
        if not cls.__v:
            cls.__v = Foo()
        return cls.__v


obj1 = Foo.get_instance()
print(obj1)    # <__main__.Foo object at 0x0000000000426C18>
obj2 = Foo.get_instance()
print(obj2)    # <__main__.Foo object at 0x0000000000426C18>

 

posted on 2018-03-05 19:22  搬马  阅读(145)  评论(0编辑  收藏  举报