为了账号安全,请及时绑定邮箱和手机立即绑定
慕课网数字资源数据库体验端
python进阶_学习笔记_慕课网
为了账号安全,请及时绑定邮箱和手机立即绑定

python进阶

廖雪峰 移动开发工程师
难度中级
时长 3小时33分
  • 任务

    Rational类虽然可以做加法,但无法做减法、乘方和除法,请继续完善Rational类,实现四则运算。

    提示:
    减法运算:__sub__
    乘法运算:__mul__
    除法运算:__div__

    • ?不会了怎么办

    • 如果运算结果是 6/8,在显示的时候需要归约到最简形式3/4。

      参考代码:

      def gcd(a, b):
          if b == 0:
              return a
          return gcd(b, a % b)
      
      class Rational(object):
          def __init__(self, p, q):
              self.p = p
              self.q = q
          def __add__(self, r):
              return Rational(self.p * r.q + self.q * r.p, self.q * r.q)
          def __sub__(self, r):
              return Rational(self.p * r.q - self.q * r.p, self.q * r.q)
          def __mul__(self, r):
              return Rational(self.p * r.p, self.q * r.q)
          def __div__(self, r):
              return Rational(self.p * r.q, self.q * r.p)
          def __str__(self):
              g = gcd(self.p, self.q)
              return '%s/%s' % (self.p / g, self.q / g)
          __repr__ = __str__
      
      r1 = Rational(1, 2)
      r2 = Rational(1, 4)
      print r1 + r2
      print r1 - r2
      print r1 * r2
      print r1 / r2


    查看全部
  • python中数学运算

    Python 提供的基本数据类型 int、float 可以做整数和浮点的四则运算以及乘方等运算。

    但是,四则运算不局限于int和float,还可以是有理数、矩阵等。

    要表示有理数,可以用一个Rational类来表示:

    class Rational(object):     def __init__(self, p, q):         self.p = p         self.q = q

    p、q 都是整数,表示有理数 p/q。

    如果要让Rational进行+运算,需要正确实现__add__:

    class Rational(object):     def __init__(self, p, q):         self.p = p         self.q = q     def __add__(self, r):         return Rational(self.p * r.q + self.q * r.p, self.q * r.q)     def __str__(self):         return '%s/%s' % (self.p, self.q)     __repr__ = __str__

    现在可以试试有理数加法:

    >>> r1 = Rational(1, 3) >>> r2 = Rational(1, 2) >>> print r1 + r2 5/6


    查看全部
  • python中 __len__

    如果一个类表现得像一个list,要获取有多少个元素,就得用 len() 函数。

    要让 len() 函数工作正常,类必须提供一个特殊方法__len__(),它返回元素的个数。

    例如,我们写一个 Students 类,把名字传进去:

    class Students(object):     def __init__(self, *args):         self.names = args     def __len__(self):         return len(self.names)

    只要正确实现了__len__()方法,就可以用len()函数返回Students实例的“长度”:

    >>> ss = Students('Bob', 'Alice', 'Tim') >>> print len(ss) 3

     

    任务

    斐波那契数列是由 0, 1, 1, 2, 3, 5, 8...构成。

    请编写一个Fib类,Fib(10)表示数列的前10个元素,print Fib(10) 可以打印出数列的前 10 个元素,len(Fib(10))可以正确返回数列的个数10。

    • ?不会了怎么办

    • 需要根据num计算出斐波那契数列的前N个元素。

      参考代码:

      class Fib(object):     def __init__(self, num):         a, b, L = 0, 1, []         for n in range(num):             L.append(a)             a, b = b, a + b         self.numbers = L     def __str__(self):         return str(self.numbers)     __repr__ = __str__     def __len__(self):         return len(self.numbers) f = Fib(10) print f print len(f)


    查看全部
    0 采集 收起 来源:python中 __len__

    2019-01-09

  • class Student(object):


        def __init__(self, name, score):

            self.name = name

            self.score = score


        def __str__(self):

            return '(%s: %s)' % (self.name, self.score)


        __repr__ = __str__


        def __cmp__(self, s):

            if self.score<s.score:

                return 1

            elif self.score>s.score:

                return -1

            else:

                if self.name<s.name:

                    return -1

                elif self.name>s.name:

                    return 1

                else:

                    return 0

            


    L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)]

    print sorted(L)


    查看全部
    0 采集 收起 来源:python中 __cmp__

    2019-01-09

  • python中 __cmp__

    对 int、str 等内置数据类型排序时,Python的 sorted() 按照默认的比较函数 cmp 排序,但是,如果对一组 Student 类的实例排序时,就必须提供我们自己的特殊方法 __cmp__():

    class Student(object):     def __init__(self, name, score):         self.name = name         self.score = score     def __str__(self):         return '(%s: %s)' % (self.name, self.score)     __repr__ = __str__     def __cmp__(self, s):         if self.name < s.name:             return -1         elif self.name > s.name:             return 1         else:             return 0

    上述 Student 类实现了__cmp__()方法,__cmp__用实例自身self和传入的实例 s 进行比较,如果 self 应该排在前面,就返回 -1,如果 s 应该排在前面,就返回1,如果两者相当,返回 0。

    Student类实现了按name进行排序:

    >>> L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 77)] >>> print sorted(L) [(Alice: 77), (Bob: 88), (Tim: 99)]

    注意: 如果list不仅仅包含 Student 类,则 __cmp__ 可能会报错:

    L = [Student('Tim', 99), Student('Bob', 88), 100, 'Hello'] print sorted(L)

    请思考如何解决。

    任务

    请修改 Student 的 __cmp__ 方法,让它按照分数从高到底排序,分数相同的按名字排序。

    • ?不会了怎么办

    • 需要先比较 score,在 score 相等的情况下,再比较 name。

      参考代码:

      class Student(object):     def __init__(self, name, score):         self.name = name         self.score = score     def __str__(self):         return '(%s: %s)' % (self.name, self.score)     __repr__ = __str__     def __cmp__(self, s):         if self.score == s.score:             return cmp(self.name, s.name)         return -cmp(self.score, s.score) L = [Student('Tim', 99), Student('Bob', 88), Student('Alice', 99)] print sorted(L)


    查看全部
    0 采集 收起 来源:python中 __cmp__

    2019-01-09

  • python中 __str__和__repr__

    如果要把一个类的实例变成 str,就需要实现特殊方法__str__():

    class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender     def __str__(self):         return '(Person: %s, %s)' % (self.name, self.gender)

    现在,在交互式命令行下用 print 试试:

    >>> p = Person('Bob', 'male') >>> print p (Person: Bob, male)

    但是,如果直接敲变量 p:

    >>> p <main.Person object at 0x10c941890>

    似乎__str__() 不会被调用。

    因为 Python 定义了__str__()和__repr__()两种方法,__str__()用于显示给用户,而__repr__()用于显示给开发人员。

    有一个偷懒的定义__repr__的方法:

    class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender     def __str__(self):         return '(Person: %s, %s)' % (self.name, self.gender)     __repr__ = __str__

    任务

    请给Student 类定义__str__和__repr__方法,使得能打印出<Student: name, gender, score>:

    class Student(Person):     def __init__(self, name, gender, score):         super(Student, self).__init__(name, gender)         self.score = score
    • ?不会了怎么办

    • 只要为Students 类加上__str__()和__repr__()方法即可。

      参考代码:

      class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender class Student(Person):     def __init__(self, name, gender, score):         super(Student, self).__init__(name, gender)         self.score = score     def __str__(self):         return '(Student: %s, %s, %s)' % (self.name, self.gender, self.score)     __repr__ = __str__ s = Student('Bob', 'male', 88) print s


    查看全部
  • 特殊方法:

    https://img1.sycdn.imooc.com//5c35628a0001129110780588.jpg

    https://img1.sycdn.imooc.com//5c3562e10001644208190519.jpg

    https://img1.sycdn.imooc.com//5c3563040001abad10470445.jpg

    https://img1.sycdn.imooc.com//5c35632a0001437a10920589.jpg

    https://img1.sycdn.imooc.com//5c35634f0001179009310621.jpg

    查看全部
  • 任务

    对于Person类的定义:

    class Person(object):
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender

    希望除了 name和gender 外,可以提供任意额外的关键字参数,并绑定到实例,请修改 Person 的 __init__()定 义,完成该功能。

    • ?不会了怎么办

    • 传入**kw 即可传入任意数量的参数,并通过 setattr() 绑定属性。

      参考代码:

      class Person(object):
          def __init__(self, name, gender, **kw):
              self.name = name
              self.gender = gender
              for k, v in kw.iteritems():
                  setattr(self, k, v)
      
      p = Person('Bob', 'Male', age=18, course='Python')
      print p.age
      print p.course


    查看全部
  • python中获取对象信息

    拿到一个变量,除了用 isinstance() 判断它是否是某种类型的实例外,还有没有别的方法获取到更多的信息呢?

    例如,已有定义:

    class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender class Student(Person):     def __init__(self, name, gender, score):         super(Student, self).__init__(name, gender)         self.score = score     def whoAmI(self):         return 'I am a Student, my name is %s' % self.name

    首先可以用 type() 函数获取变量的类型,它返回一个 Type 对象:

    >>> type(123) <type 'int'> >>> s = Student('Bob', 'Male', 88) >>> type(s) <class '__main__.Student'>

    其次,可以用 dir() 函数获取变量的所有属性:

    >>> dir(123)   # 整数也有很多属性... ['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...] >>> dir(s) ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'score', 'whoAmI']

    对于实例变量,dir()返回所有实例属性,包括`__class__`这类有特殊意义的属性。注意到方法`whoAmI`也是 s 的一个属性。

    如何去掉`__xxx__`这类的特殊属性,只保留我们自己定义的属性?回顾一下filter()函数的用法。

    dir()返回的属性是字符串列表,如果已知一个属性名称,要获取或者设置对象的属性,就需要用 getattr() 和 setattr( )函数了:

    >>> getattr(s, 'name')  # 获取name属性 'Bob' >>> setattr(s, 'name', 'Adam')  # 设置新的name属性 >>> s.name 'Adam' >>> getattr(s, 'age')  # 获取age属性,但是属性不存在,报错: Traceback (most recent call last):   File "<stdin>", line 1, in <module> AttributeError: 'Student' object has no attribute 'age' >>> getattr(s, 'age', 20)  # 获取age属性,如果属性不存在,就返回默认值20: 20


    查看全部
  • class Student(object):

        def __init__(self, name, score):
            self.name = name
            self.__score = score

        @property
        def getscore(self):
            return self.__score

        @getscore.setter
        def score(self, score):
            if score < 0 or score > 100:
                raise ValueError('invalid score')
            self.__score = score

        @property
        def grade(self):
            if self.getscore>=80:
                return 'A'
            elif self.getscore<60:
                return 'C'
            else:
                return 'B'

    s = Student('Bob', 59)

    print s.score
    print s.getscore
    print s.grade

    s.score = 60
    print s.grade
    print s.score

    s.score = 99
    print s.grade
    print s.score


    上面代码,s.getscore 和 s.score 都是获取分数且值相同,但是s.getscore 只能读,s.score可以读 可写。由此可见@***.setter 是将下面方法装饰成该方法同名的可读写属性,即自动生成一个读方法和写方法,@property只是装饰成和方法同名的读属性,即只有一个方法,只生成一个读方法。若@***.setter 下的方法同名的话则将构成一个可读写属性




    查看全部
    0 采集 收起 来源:python中 @property

    2019-01-09

  • 任务

    +-Person
      +- Student
      +- Teacher

    是一类继承树;

    +- SkillMixin
       +- BasketballMixin
       +- FootballMixin

    是一类继承树。

    通过多重继承,请定义“会打篮球的学生”和“会踢足球的老师”。

    多重继承需要从两个或更多的类派生。

    参考代码:

    class Person(object):
        pass
    
    class Student(Person):
        pass
    
    class Teacher(Person):
        pass
    
    class SkillMixin(object):
        pass
    
    class BasketballMixin(SkillMixin):
        def skill(self):
            return 'basketball'
    
    class FootballMixin(SkillMixin):
        def skill(self):
            return 'football'
    
    class BStudent(Student, BasketballMixin):
        pass
    
    class FTeacher(Teacher, FootballMixin):
        pass
    
    s = BStudent()
    print s.skill()
    
    t = FTeacher()
    print t.skill()


    查看全部
  • python中多重继承

    除了从一个父类继承外,Python允许从多个父类继承,称为多重继承。

    多重继承的继承链就不是一棵树了,它像这样:

    class A(object):     def __init__(self, a):         print 'init A...'         self.a = a class B(A):     def __init__(self, a):         super(B, self).__init__(a)         print 'init B...' class C(A):     def __init__(self, a):         super(C, self).__init__(a)         print 'init C...' class D(B, C):     def __init__(self, a):         super(D, self).__init__(a)         print 'init D...'

    看下图:

    54daf037000142d207580552.jpg

    像这样,D 同时继承自 B 和 C,也就是 D 拥有了 A、B、C 的全部功能。多重继承通过 super()调用__init__()方法时,A 虽然被继承了两次,但__init__()只调用一次:

    >>> d = D('d') init A... init C... init B... init D...

    多重继承的目的是从两种继承树中分别选择并继承出子类,以便组合功能使用。

    举个例子,Python的网络服务器有TCPServer、UDPServer、UnixStreamServer、UnixDatagramServer,而服务器运行模式有 多进程ForkingMixin 和 多线程ThreadingMixin两种。

    要创建多进程模式的 TCPServer:

    class MyTCPServer(TCPServer, ForkingMixin)     pass

    要创建多线程模式的 UDPServer:

    class MyUDPServer(UDPServer, ThreadingMixin):     pass

    如果没有多重继承,要实现上述所有可能的组合需要 4x2=8 个子类。


    查看全部
  • python中多态

    类具有继承关系,并且子类类型可以向上转型看做父类类型,如果我们从 Person 派生出 Student和Teacher ,并都写了一个 whoAmI() 方法:

    class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender     def whoAmI(self):         return 'I am a Person, my name is %s' % self.name class Student(Person):     def __init__(self, name, gender, score):         super(Student, self).__init__(name, gender)         self.score = score     def whoAmI(self):         return 'I am a Student, my name is %s' % self.name class Teacher(Person):     def __init__(self, name, gender, course):         super(Teacher, self).__init__(name, gender)         self.course = course     def whoAmI(self):         return 'I am a Teacher, my name is %s' % self.name

    在一个函数中,如果我们接收一个变量 x,则无论该 x 是 Person、Student还是 Teacher,都可以正确打印出结果:

    def who_am_i(x):     print x.whoAmI() p = Person('Tim', 'Male') s = Student('Bob', 'Male', 88) t = Teacher('Alice', 'Female', 'English') who_am_i(p) who_am_i(s) who_am_i(t)

    运行结果:

    I am a Person, my name is Tim I am a Student, my name is Bob I am a Teacher, my name is Alice

    这种行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。

    由于Python是动态语言,所以,传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可:

    class Book(object):     def whoAmI(self):         return 'I am a book'

    这是动态语言和静态语言(例如Java)最大的差别之一。动态语言调用实例方法,不检查类型,只要方法存在,参数正确,就可以调用。


    查看全部
    0 采集 收起 来源:python中多态

    2019-01-09

  • python中判断类型

    函数isinstance()可以判断一个变量的类型,既可以用在Python内置的数据类型如str、list、dict,也可以用在我们自定义的类,它们本质上都是数据类型。

    假设有如下的 Person、Student 和 Teacher 的定义及继承关系如下:

    class Person(object):     def __init__(self, name, gender):         self.name = name         self.gender = gender class Student(Person):     def __init__(self, name, gender, score):         super(Student, self).__init__(name, gender)         self.score = score class Teacher(Person):     def __init__(self, name, gender, course):         super(Teacher, self).__init__(name, gender)         self.course = course p = Person('Tim', 'Male') s = Student('Bob', 'Male', 88) t = Teacher('Alice', 'Female', 'English')

    当我们拿到变量 p、s、t 时,可以使用 isinstance 判断类型:

    >>> isinstance(p, Person) True    # p是Person类型 >>> isinstance(p, Student) False   # p不是Student类型 >>> isinstance(p, Teacher) False   # p不是Teacher类型

    这说明在继承链上,一个父类的实例不能是子类类型,因为子类比父类多了一些属性和方法。

    我们再考察 s :

    >>> isinstance(s, Person) True    # s是Person类型 >>> isinstance(s, Student) True    # s是Student类型 >>> isinstance(s, Teacher) False   # s不是Teacher类型

    s 是Student类型,不是Teacher类型,这很容易理解。但是,s 也是Person类型,因为Student继承自Person,虽然它比Person多了一些属性和方法,但是,把 s 看成Person的实例也是可以的。

    这说明在一条继承链上,一个实例可以看成它本身的类型,也可以看成它父类的类型。


    查看全部
  • @property的实现比较复杂,我们先考察如何使用。把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值相当于java中的get set 配对方法

    ,@score.setter是前一个@property装饰后的副产品。

    @birth.setter

    @age.setter

    查看全部
    1 采集 收起 来源:python中 @property

    2019-01-09

举报

0/150
提交
取消
课程须知
本课程是Python入门的后续课程 1、掌握Python编程的基础知识 2、掌握Python函数的编写 3、对面向对象编程有所了解更佳
老师告诉你能学到什么?
1、什么是函数式编程 2、Python的函数式编程特点 3、Python的模块 4、Python面向对象编程 5、Python强大的定制类
友情提示:

您好,此课程属于迁移课程,您已购买该课程,无需重复购买,感谢您对慕课网的支持!