廖雪峰Python3学习笔记1

本文是笔者学习廖雪峰Python3教程的笔记,在此感谢廖老师的教程让我们这些初学者能够一步一步的进行下去.如果读者想学习完成的教程,请访问廖雪峰Python3教程,笔记如有侵权,请告知删除...

__slots__

  • 使用__slots__来限制实例能添加的属性
  • 使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的
  • 除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__。
class Student(object): 
  __slots__ = ('name', 'age')

@property

  • 把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值
class Screen(object):

   @property
   def width(self):
       return self._width

   @width.setter
   def width(self, value):
       self._width = value

   @property
   def height(self):
       return self._height

   @height.setter
   def height(self, value):
       self._height = value

   @property
   def resoluation(self):
       return self._width*self._height

MixIn

MixIn是一种多继承, 只需要在定义类型后面的小括号里用逗号分割添加新的继承类即可

class MyTCPServer(TCPServer, ForkingMixIn):
   pass
   ```

#定制类

类似\_\_slots\_\_这种形如\_\_xxx\_\_的变量或者函数名就要注意,这些在Python中是有特殊用途的。例如\_\_len\_\_()方法是为了能让class作用于len()函数。

- ## \_\_str__

def str(self):
return 'Student object (name: %s)' % self.name

在类中写这段 使用print进行打印输出的时候就会按照格式显示,但是如果不用print打印则不会按照格式输出

 这是因为直接显示变量调用的不是\_\_str\_\_而是\_\_repr\_\_()来返回用户看到的字符串,而\_\_repr\_\_()返回的是程序开发者所看到的字符串,也就是说\_\_repr\_\_()是为调试服务的.
 
 解决办法是在写一个\_\_repr\_\_()方法,但是由于\_\_str\_\_和\_\_repr\_\_()方法通常一样,所以简单的写法为
 
 ```class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return 'Student object (name=%s)' % self.name
    __repr__ = __str__
    ```
    
- ## \_\_iter\_\_
    
    如果一个类想被用于for...in循环,类似list和tuple.那就必须实现一个\_\_iter\_\_()方法,该方法的返回值是一个可迭代的对象,然后Python的for循环就会不断调用\_\_next\_\_()方法拿到循环的下一个值,知道遇到stopIteration抛出异常为止
    
    ```
    #斐波那契数列
    class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration();
        return self.a # 返回下一个值
  • __getitem__

实现了__iter__方法之后,虽然能够使用for循环进行迭代,但是并不能像list似的使用下标来访问其中的元素,若要实现该功能则需要实现__getitem__()方法

class Fib(object):
   def __getitem__(self, n):
       a, b = 1, 1
       for x in range(n):
           a, b = b, a + b
       return a

这样做虽然可以使用下标进行访问了,但是对于list(range(10))[2:9]这样的切片方法却行不通,原因是getitem()传入的参数可能是一个int,也可能是一个切片对象slice,这个时候就需要就传入的参数进行判断了

  • __getattr__

使用Python的另一个机制是写一个getattr()方法,动态返回一个属性。可以避免因为调用不存在的属性出现的错误.这个方法只有在没有找到属性的情况下才会调用, 这个方法同样可以返回一个函数.

class Student(object):

   def __init__(self):
       self.name = 'Michael'

   def __getattr__(self, attr):
       if attr=='score':
           return 99
# 返回一个函数
class Student(object):

   def __getattr__(self, attr):
       if attr=='age':
           return lambda: 25

这样在调用Student类的score这个不存在的属性的时候就不会出现错误信息而是返回99这个数

  • __call__

一个对象实例可以有自己的属性和方法,当我们调用实例方法时使用__call__可以直接在实例本身上调用方法.

任何类,只需要定义一个__call__()方法,就可以直接对实例进行调用.

class Student(object): 
  def __init__(self, name): 
    self.name = name
 def __call__(self): 
    print('My name is %s.' % self.name)

# 调用方法:
s = Student('Joe')
s() # self参数不要传入
My name is Joe.

枚举类

  • Python中的枚举类型需要先从enum模块中引入Enum类.
    然后创建一个枚举
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

如上所示即获得了Month类型的枚举,可以使用Month.Jan, Month.Feb 这种类型进行访问, 也可以使用forin来遍历

for name, member in Month.__members__.items():
   print(name, '=>', member, ',', member.value)

member.value是自动给枚举赋值的,赋值从1开始

  • 如果要精确的控制枚举类型, 可以从Enum派生出自定义类.
from enum import Enum, unique
@unique
class Weekday(Enum):
   Sun = 0 # Sun的value被设定为0
   Mon = 1
   Tue = 2
   Wed = 3
   Thu = 4
   Fri = 5
   Sat = 6

其中装饰器@unique的作用是检查name所对应的value值是否唯一

  • 访问方式有很多

    例如:
    Weekday['Tue']
    Weekday(1)
    Weekday.Sun
    Weekday.Tue.value
    ......

元类

  • type()

    Python是一门动态语言,他所有的类和方法都不是在编译的时候创建的,而是在运行的时候创建的.

    type()既可以返回一个class类型,也使用type()可以在运行时动态的创建一个class.无需经过class name(object):来定义

    • 首先定义一个方法
    def fn(self, name = 'world'):
        print('Hello %s' % name)
    
    • 使用type()方法创建一个class

    Hello = type('Hello', (object, ), dict(hello = fn))

    • type()的三个参数

    1.第一个参数是定义的class的名字
    2.第二个参数是继承的类,这是一个tuple.如果不是多继承的话,需要传入一个单元素的元组(object,)
    3.第三个参数是方法名与函数的绑定,将在类外面定义的函数绑定到类的方法上

你可能感兴趣的:(廖雪峰Python3学习笔记1)