欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python day5

程序员文章站 2024-02-24 14:43:40
...

python day5

面向对象高级编程

使用slots

动态绑定允许在class之外给类添加属性和方法。
如果要对这种动态绑定加限制,用__slots__

class Student(object):
    __slots__ = ('name', 'age')
    #使用元组定义允许使用动态绑定的属性

没有被放入__slots__的不允许动态绑定。
子类不受影响。
如果子类也有__slots__,则子类和父类__slots__定义的都允许动态绑定。

__slots__可以大大减少内存的占用。因为对象属性是依靠字典存储的。而__slots__可以减少对内存的负担。

__slots__需要对每一个继承对子类都重新定义一遍;而且不够灵活。

除非编写的类会有上万个对象,否则不推荐使用。

@property

装饰器
把方法变成属性调用
在get方法前加上@property,方法变成属性;自动生成另一个装饰器@属性.setter。

class Student(object):

    @property
    def get_gender(self):
        return self.__gender

    def set_gender(self, gender):
        if gender == 'male' or gender == 'female':
            self.__gender = gender
        else:
            raise ValueError('invalid gender')


s = Student
s.gender = 'male'
print(s.gender)

减少调用者的负担

多重继承

Java的多继承是用接口实现的。
python 通过继承多个类实现MixIn。

class Dog(Mammal, Animal,  Runnable):
    pass

python 多重继承的拓扑排序:
https://kevinguo.me/2018/01/19/python-topological-sorting/
使用C3 算法。
继承关系是一个有向无环图,从入度为0处开始,如果多个入度为0,则取最左。

定制类

__str__()用户看
__repr__()调试看
改变控制台打印的信息
一般__repr__ == __str__
__iter__()方法返回迭代对象

__getitem__()
__setitem__()
__delitem__()
将自己定义的类表现的与list、tuple、dict没什么区别。

__getattr__()
动态获取类的属性
如果在调用类的属性时,没有该属性,那么会取调用这个方法。
__getattr__()默认返回None。

__call__()
使得对象变得可以被调用
callable()判断一个对象是否是可以被调用的对象。

枚举类

可以直接使用enum,也可以定义自己的枚举类。

# coding _utf-8

from enum import Enum

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

for name, member in Month.__members__.items():
    print(name, '==>', member, ',', member.value)#value默认从1开始。
('Jan', '==>', <Month.Jan: 1>, ',', 1)
('Feb', '==>', <Month.Feb: 2>, ',', 2)
('Mar', '==>', <Month.Mar: 3>, ',', 3)
('Apr', '==>', <Month.Apr: 4>, ',', 4)
('May', '==>', <Month.May: 5>, ',', 5)
('Jun', '==>', <Month.Jun: 6>, ',', 6)
('Jul', '==>', <Month.Jul: 7>, ',', 7)
('Aug', '==>', <Month.Aug: 8>, ',', 8)
('Sep', '==>', <Month.Sep: 9>, ',', 9)
('Oct', '==>', <Month.Oct: 10>, ',', 10)
('Nov', '==>', <Month.Nov: 11>, ',', 11)
('Dec', '==>', <Month.Dec: 12>, ',', 12)

在pycharm中无法导入enum模块,最后清除缓存,重启。

自定义枚举类型:

from enum import Enum, unique

unique
class Month(Enum):
    Jan = 0#value可以自己编写
    Feb = 1
    Mar = 2
    Apr = 3
    May = 4
    Jun = 5
    Jul = 6
    Aug = 7
    Sep = 8
    Oct = 9
    Nov = 10
    Dec = 11

@unique保证value不会重复。

使用元类

type()

type()可以检查一个对象或者变量的类型,也可以动态创建一个类。
类的类型是type。

metaclass

类似于元数据的概念。
元类。
定义元类,就可以根据元类创建类,然后根据类创建对象。

错误、调试、测试

修复bug、检查用户输入、处理异常、测试代码

错误处理

Java是try...catch...finally
python是try...except...finally
或者try...except...else...finally

python所有的错误都继承自BaseException。
java throw
python raise
如果不带参数,raise将错误原样抛出。

调试

assert
断言,调试结束可以关闭

logging

级别:
debug
info
warning
error

import logging
logging.basicConfig(level=logging.ERROR)

s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)

logging调试最强大,ide调试最方便

单元测试

# -*- coding: utf-8 -*-
import unittest

class Student(object):
    def __init__(self, name, score):
        self.name = name
        if not (score >= 0 and score <= 100):
            raise ValueError('invalid score')
        self.score = score

    def get_grade(self):
        if self.score >= 80:
            return 'A'
        elif self.score >= 60:
            return 'B'
        return 'C'


class TestStudent(unittest.TestCase):

    def test_80_to_100(self):
        s1 = Student('Bart', 80)
        s2 = Student('Lisa', 100)
        self.assertEqual(s1.get_grade(), 'A')
        self.assertEqual(s2.get_grade(), 'A')

    def test_60_to_80(self):
        s1 = Student('Bart', 60)
        s2 = Student('Lisa', 79)
        self.assertEqual(s1.get_grade(), 'B')
        self.assertEqual(s2.get_grade(), 'B')

    def test_0_to_60(self):
        s1 = Student('Bart', 0)
        s2 = Student('Lisa', 59)
        self.assertEqual(s1.get_grade(), 'C')
        self.assertEqual(s2.get_grade(), 'C')

    def test_invalid(self):
        s1 = Student('Bart', -1)
        s2 = Student('Lisa', 101)
        with self.assertRaises(ValueError):
            s1.get_grade()
        with self.assertRaises(ValueError):
            s2.get_grade()

if __name__ == '__main__':
    unittest.main()

文档测试

文档测试既可以测试,也可以作为示例程序。

IO

分为:
同步IO:效率低,简单
异步IO:效率高,复杂,有轮询模式和回调模式
本质上是高效的cpu与低效的外设之间的矛盾

文件读写

读input

try:
    f = open('haha.txt', 'r')#r表示读
    f.read()
except IOError as e:
    pass
finally:
    if f:
        f.close()

读进来的数据是一个str类型的对象。
比较麻烦
简写方式是:

with open('haha.txt', 'r') as f:
    f.read()

read() 一次性读取文件的全部数据
read(size) 一次最多读取size字节的数据
readline() 一次读取一行数据
readlines() 一次读取全部数据,并返回list,按照行存储所有的数据