首页 > 代码库 > Python 面向对象

Python 面向对象

 方法:所有的方法是属于类的

1、普通方法:至少一个self,对象执行

2、静态方法:任意参数,类执行

3、类方法:至少一个cls,类执行

 

类方法:

在Python的面向对象方法中,支持3种,一种是普通方法,静态方法,类方法

类方式其实是静态方法的一种特殊形式:

class Foo:
    def __int__(self, name):
        self.name = name

    # 类方法是静态方法一种,由类来调用
    @classmethod
    def f2(cls):  # 必须至少要有一个参数cls
        print(cls)


f = Foo()
f.f2()  # 不用添加参数,自动把类名传入cls参数

 cls是类名,如果加上()就是创建对象

 

 

属性

class Pager:
    def __init__(self, all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1, a2 = divmod(self.all_count, 10)
        if a2 == 0:
            return a1
        else:
            return a1 + 1


p = Pager(101)
ret = p.all_pager
print(ret)

属性就是通过是用调用字段的方式调用类里面的方法(去掉括号),其它功能跟调用方法一致,在写代码的时候可能比较好看。

但是问题来了,字段可以进行赋值,你这个可以吗?

class Pager:
    def __init__(self, all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1, a2 = divmod(self.all_count, 10)
        if a2 == 0:
            return a1
        else:
            return a1 + 1


p = Pager(101)
p.all_pager = 10

# 输出
Traceback (most recent call last):
File "D:/oop2.py", line 26, in <module>
p.all_pager = 10
AttributeError: cant set attribute

比如我想对p.all_pager重新赋值为10,那程序肯定报错。

那可以设置吗?

答案是:肯定可以,如果你想设置需要在类里面创建一个方法,并在方法上加上一个装饰器@[方法名字].setter

class Pager:
    def __init__(self, all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1, a2 = divmod(self.all_count, 10)
        if a2 == 0:
            return a1
        else:
            return a1 + 1

    @all_pager.setter
    def all_pager(self, value):
        print(value)


p = Pager(101)

p.all_pager = 10

# 输出
10

上面我们介绍了,可以获取,可以设置,还缺少一个可以删除,那下面我们来实现删除

实现删除其实跟实现设置一样,需要在类里面定义一个方法并在方法上加上@[方法名字].deleter

class Pager:
    def __init__(self, all_count):
        self.all_count = all_count

    @property
    def all_pager(self):
        a1, a2 = divmod(self.all_count, 10)
        if a2 == 0:
            return a1
        else:
            return a1 + 1

    @all_pager.setter
    def all_pager(self, value):
        print(value)

    @all_pager.deleter
    def all_pager(self):
        print(del all_pager)

p = Pager(101)

del p.all_pager

到此为止,属性伪造成字段的访问方式后,完全可以进行输出、设置、及删除了

 

类继承-重构子类使用super的初始化方法

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


class Student(Member):
    def __init__(self, name, age, sex, sid):
        super(Student, self).__init__(name, age, sex)
        self.sid = sid

    def info(self):
        info = ‘‘‘
        学生名称:{name}
        学生年龄:{age}
        学生性别:{sex}
        学生编号:{sid}
        ‘‘‘.format(name=self.name, age=self.age, sex=self.sex, sid=self.sid)
        print(info)


class Teacher(Member):
    def __init__(self, name, age, sex, tid, salary):
        super(Teacher, self).__init__(name, age, sex)
        self.tid = tid
        self.salary = salary

    def info(self):
        info = ‘‘‘
        老师名称:{name}
        老师年龄:{age}
        老师性别:{sex}
        老师编号:{sid}
        老师工资:{salary}
        ‘‘‘.format(name=self.name, age=self.age, sex=self.sex, sid=self.tid, salary=self.salary)
        print(info)


s1 = Student(Tom, 18, , S0001)
s1.info()

t1 = Teacher(jerry, 28, , T0001, 0)
t1.info()

 

类的多继承,适用于python 3.x

class C_2:
    def f2(self):
        print(C-2)


class C_1(C_2):
    def f2(self):
        print(C-1)


class C0(C_2):
    def f1(self):
        print(C0)


class C1(C0):
    def f1(self):
        pass


class C2(C_1):
    def f2(self):
        print(c2)


class C3(C1, C2):
    def f3(self):
        pass


obj = C3()
obj.f2()

技术分享

 

 

总结:

当没有共同的父类的时候,深度优先,当有共同父类的时候广度优先

 

类的魔术方法

Python在类中存在一些特殊方法,被称为"魔术方法",下面我们来见识一下:

1、__init__ 重要程度: *****

按照字面的意思其实就是初始化,它在类中有什么用呢?相信学习面向对象的人第一个接触的就是它了,我的理解是:在实例化对象的时候被自动触发并执行

class Foo:
    def __init__(self, name, age):
        self.Name = name
        self.Age = age
        print(我开始执行了)


f = Foo(chen, 20)

# 输出
我开始执行了

通过例子可以看出,我只是实例化了类,没有进行任何动作,就打印出来了

2、__dict__ 重要程度: ***

用于储存类或实例的属性,当使用类+__dict__打印类的属性,使用实例+__dict__打印实例的属性

class Foo:
    country = CN

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

f = Foo(chen, 20)
print(f.__dict__)  # 以字典形式显示实例的属性
print(Foo.__dict__)  # 以字典形式显示类的属性

# output
{Name: chen, Age: 20}
{__weakref__: <attribute __weakref__ of Foo objects>, __doc__: None, __module__: __main__, country: CN, __init__: <function Foo.__init__ at 0x000000000377BA60>, __dict__: <attribute __dict__ of Foo objects>}

 3、__doc__ 描述类的信息  重要程度: ***

class Foo:
    """
    这是一个显示doc的类的例子
    """
    def __init__(self):
        pass

print(Foo.__doc__)

# 输出
这是一个显示doc的类的例子

4、__call__ 重要程度: *****

在对象后边加(),触发__call__方法

class Foo:

    def __call__(self, *args, **kwargs):
        print(调用我吧)

f = Foo()
f()

5、__del__ : 析构方法 重要程度: *

在垃圾回收前执行它,貌似没啥用

6、__class__ 和__module__  重要程度: *

class Foo:
    def __init__(self):
        pass


f = Foo()
print(f.__class__)
print(f.__module__)

# 输出
<class __main__.Foo>
__main__

7、__str__

使用这个方式打印f对象输出的是对象,那能否输出内容呢?答案是肯定的,使用__str__

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

f = Foo(tom, 11)
print(f)

# 输出
<__main__.Foo object at 0x000000000337B278>

修改一下代码:这样你在打印对象的时候就可以看见被封装的数据了

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

    def __str__(self):
        return {name}--{age}.format(name=self.name, age=self.age)


f = Foo(tom, 11)
print(f)

# 输出
tom--11

 7、__add__

技术分享

8、__getitem__、__setitem__、__delitem__ 重要程度: *****

搞清楚__getitem__之前,我们先看看字典的实现方法:

dic = {‘k1‘:‘v1‘} 等同于 dic = dict(k1=v1)

当我们取值的时候,可以

dic[‘k1‘] 那这个怎么实现呢?

只要在对象+[]中括号就是调用__getitem__方法

class Foo:

    def __getitem__(self, item):
        print(item)

f = Foo()
f[abcd]

# 输出
abcd
class Foo:
    def __setitem__(self, key, value):
        print(key, value)

f = Foo()
f[k1] = 123
class Foo:

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


f = Foo()
del f[k1]

利用上述模块,做一个有序字典,转自武sir

class MyDict(dict):
    def __init__(self):
        super(MyDict, self).__init__()
        self.li = []

    def __setitem__(self, key, value):
        self.li.append(key)
        super(MyDict, self).__setitem__(key, value)

    def __str__(self):
        tmp_list = []
        for key in self.li:
            value = self.get(key)
            tmp_list.append("‘%s‘:%s" % (key, value))
        temp_str = { + ,.join(tmp_list) + }
        return temp_str


obj = MyDict()
obj[k1] = 123
obj[k2] = 123
print(obj)

 

 

 

9、__iter__

默认对象是不可迭代的

 

 

异常处理

技术分享

完整代码块:

try:
    # 逻辑代码放这里
    pass
except IndexError as e:  # 当逻辑处理块出现错误后,顺序查看错误原因,如果为IndexError这个块先进行处理,否则执行下边的except Exception语句
    print(e)  # str
except Exception as e:
    print(e)
else:
    # 逻辑处理块未出现异常,执行这里代码
    pass
finally:
    # 释放资源
    # 不管你上边是否出现错误,本块永远执行,在逻辑处理块执行完毕后。
    pass

 

Python 面向对象