Python 面向对象

面向对象

面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用

如何创建类,方法,对象?

class Father(): # 创建类
    def __init__(self): # 构造方法(初始化), self = 对象(obj)
        pass

    def show(self): # 创建方法
        return None

obj = Father() # 1.创建对象 2. 调用__init__方法

obj.show() # 调用方法
View Code

面向对象的三大特征

1、封装

封装,就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

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

    def show(self):
        print(self.name,self.age)

obj = Father("kidd",16)
obj2 = Father("jim",17)
View Code

2、继承
子类继承父类

class Father():
    def basketball(self):
        print("I like basketball")
    def tennis(self):
        print("I like tennis")
    def swimming(self):
        print("I don't like swimming")

class Son(Father): # 继承父类
    # 当父亲和儿子都喜欢时
    def basketball(self):
        # super(子类名,self).父类方法
        super(Son,self).basketball() # 调用父类的方法
        print("I like basketball,too")
    def tennis(self):
        Father.tennis(self)
        print("I like tennis,too")

    # 当父亲不喜欢,儿子喜欢时
    # 重构
    def swimming(self):
        print("I like swimming")

son = Son()
son.basketball()
son.tennis()
son.swimming()

# 输出
I like basketball
I like basketball,too
I like tennis
I like tennis,too
I like swimming
View Code

多继承

class Grandfather():
    def basketball(self):
        print("I like basketball -G")
    def soccer(self):
        print("I like soccer -G")

class Father():
    def basketball(self):
        print("I like basketball -F")
    def tennis(self):
        print("I like tennis -F")
    def swimming(self):
        print("I don't like swimming -F")

class Son(Father,Grandfather):
    pass
son = Son()

son.soccer() # 儿子找 ---> 没找到 ---> 父亲找 ---> 没找到 ---> 祖父找 ---> 找到了

son.basketball() # 儿子找 ---> 没找到 ---> 父亲找 ---> 找到了

# 多继承特点
左侧优先
同一个根时,根最后执行
View Code

 3、多态

 Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态

同时执行多个方法

就是说执行了子类的方法,又同时执行父类的方法

super(type[, object-or-type])

class GrandFather():
    def __init__(self):
        self.show()
    def show(self):
        print("GrandFather -- show")

class Father(GrandFather):
    pass

class Son(Father):
    def __init__(self):
        super(Son,self).__init__()

s = Son()
View Code

当然了,我也可以不用super,直接用  类+方法

什么是字段,方法?

字段分为:

普通字段 (执行只能通过对象访问)

静态字段 (执行 可以通过对象访问 也可以通过类访问)

class Foo():
    operator = "Kidd" # 静态字段

    def __init__(self):
        self.other = "Jim" # 普通字段
View Code

方法分为:

普通方法 (由对象来调用)

静态方法 (由类直接调用)

类方法 (由类直接调用)

class Foo():
    def general(self): # 普通方法
        print("General method")
    
    @staticmethod # 静态方法
    def sta():
        print("Static method")
    
    @classmethod # 类方法
    def cls(cls):
        print("class method")
View Code

property()

第一个参数是方法名,调用 对象.属性 时自动触发执行方法

第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法

第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法

第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息

class Foo:

    def get_bar(self):
        return 'wupeiqi'

    # *必须两个参数
    def set_bar(self, value):
        return 'set value' + value

    def del_bar(self):
        return 'wupeiqi'

    BAR = property(get_bar, set_bar, del_bar, '自定义解释')

obj = Foo()

obj.BAR              # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex"     # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del Foo.BAR          # 自动调用第三个参数中定义的方法:del_bar方法
obj.BAE.__doc__      # 自动获取第四个参数中设置的值:description...
View Code

成员修饰符

共有成员

私有成员, 指无法直接访问,只能间接访问

class Student():
    def __init__(self):
        self.id = "001" # 共有字段
        self.__name = "Kidd" # 私有字段
    def common(self): # 共有方法
        return self.id
    def __private(self):# 私有方法
        return self.__name
    def callable(self):
        c = self.common()
        p = self.__private() # 间接的访问
        return c,p
s = Student()

print(s.id) # 001
print(s.__name) # 报错
print(s.callable()) # ('001', 'Kidd')


只需要在字段,方法前加 __(两个下划线)即可变成私有
View Code

特殊成员

__init__  __call__  __int__  __str__

class Foo():
    def __init__(self):
        print("init")
    def __call__(self, *args, **kwargs):
        print("call")
    def __int__(self):
        return 123
    def __str__(self):
        return "str"
f = Foo() # 类调用(),触发__init__方法

f() # 对象调用(),触发__call__方法

print(int(f))# 当对象调用int方法时,它先执行对象中的__int__方法

print(f) # 为什这条语句会直接触发__str__?
# 因为 print 语句其实是 print(str()) , so---> print(str(f))
View Code

 obj.__dict__

class Foo():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def other(self):
        self.gender = "male"
f = Foo("Kidd",16)
dic = f.__dict__ # 将对象中封装的所有内容,通过字典形式返回

print(dic) # {'name': 'Kidd', 'age': 16}
View Code

__getitem__  __setitem__  __delitem__

# 对象[] 的操作

class Foo():
    def __init__(self,name,age):
        self.name = name
        self.age = age
        self.__dic = self.__dict__ # 设置私有成员,获取对象中封装的所有内容
    def __getitem__(self,item): # 查看时,  f["name"]
        return self.__dic[item]

    def __setitem__(self, key, value): # 设置时, f["age"] = 17
        self.__dic[key] = value
        
    def __delitem__(self, key): # 删除时,del f["age"]
        self.__dic.pop(key)
f = Foo("Kidd",16)

value = f["name"]

f["age"] = 17

del f["age"]
View Code
class T(object):
    "实现单利"
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"_instance"):
            cls._instance = super().__new__(cls)
        return cls._instance
    
    "构造方法"
    def __init__(self,l):
        self.l = l
    
    
    def __getitem__(self, item):
        if item >= 0 :
            for n,i in enumerate(self.l):
                if n==item:
                    return i
        else:
            l = reversed(self.l)
            for n,i in enumerate(l,1):
                if n == abs(item):
                    return i

    def __setitem__(self, key, value):
        print(key,value)

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

t = T(list(range(1,11)))

print(t[-1])
t["l"] = 0
del t["l"]
View Code

__iter___

class Foo():
    def __iter__(self):
        a = [1,2,3]
        return iter(a)

f = Foo()

for i in f:
    print(i)

# 如果类中有__iter__方法,对象 ---->可迭代对象
# for 循环类的对象 , 执行类中的__iter__方法 , 取返回值做可迭代对象
View Code

异常处理

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
常用
ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
更多异常
# 需要Try的代码
try:
    pass

# 有异常
except Exception as e:
    print(e)

# 无异常
else:
    print("No Exception")

# 不管有没有异常,finally都要执行
finally:
    print("Try Finish")
处理异常流程

 自定义异常 与 主动触发异常

class Except(Exception):
    def __init__(self,error):
        self.error = error
    def __str__(self):
        return self.error

try:
    raise Except("Custom Exception") # 主动触发异常

except Except as e:
    print(e)
View Code

断言

# 如果条件成立,程序继续执行
# 否则,报错
assert 1 == 1
assert 1 == 2
View Code

映射

映射:通过字符串的形式操作对象中的成员,在python中,一切事物皆是对象

getattr  hasattr  setattr  delattr

class Foo():
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __call__(self, *args, **kwargs):
        show = "%s - %s"%(self.name,self.age)
        return show
    def delete(self):
        return "delete"

f = Foo("kidd",16)

# 取字段
getattr(f,"name")
# 取方法
getattr(f,"__call__")

# 字段是否存在
hasattr(f,"age")
# 方法是否存在
hasattr(Foo,"show")

# 设置字段
setattr(f,"age",17)

# 删除字段
delattr(f,"name")
# 删除方法
delattr(Foo,"delete")
View Code

单例模式

如:让同学展示自己的姓名,年龄

class Students:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def __call__(self, *args, **kwargs):
        content = '''自我介绍
        %s -- %s'''%(self.name,self.age)
        return content

s1 = Students("kidd",16)()
s2 = Students("bob",15)()
创建多个实例
import time
import threading
import random


class Member(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        i = random.randint(1, 3)
        print(i)
        time.sleep(i)

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Member, "_instance"):
            with Member._instance_lock:
                if not hasattr(Member, "_instance"):
                    Member._instance = Member(*args, **kwargs)
            return Member._instance

def task():
    obj = Member.instance()
    print(obj)

for i in range(5):
    threading.Thread(target=task,).start()
多线程单例
class N():
    def __new__(cls, *args, **kwargs):
        if not hasattr(N,'_state'):
            N._state = super().__new__(cls)
        return N._state
    def __init__(self):
        pass
__new__单例

单利模式的目的:保证当前内存中仅存在单个实例,避免内存浪费!

类中的cls,self指的是谁

cls:类本身

self:实例化后的对象

class T(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,"_instance"): # T=cls,类本身
            cls._instance = super().__new__(cls)
        return cls._instance
    def __init__(self): # t1=self,类实例后的对象
        print(self)
t1=T()
t2=T()
View Code

其他相关

isinstance(obj, cls)

 检查是否obj是否是类 cls 的对象

class Foo:
    def __init__(self):
        pass

f = Foo()

result = isinstance(f,Foo)
print(result)
View Code

issubclass(sub, super)

检查sub类是否是 super 类的派生类

class Grandfather:
    pass

class Father(Grandfather):
    pass

class Son(Father):
    pass

issubclass(Son,Father) # True
issubclass(Son,Grandfather) # True
View Code
原文地址:https://www.cnblogs.com/py-peng/p/10864827.html