# 类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。 # 通过定义一个特殊的__init__方法,在创建实例的时候,就把属性绑上去 class Student(object): # 和普通的函数相比,在类中定义的函数只有一点不同,就是第一个参数永远是实例变量self # Python解释器自己会把实例变量传进去 def __init__(self, attr1, attr2): self.attr1 = attr1 self.attr2 = attr2 pass def get_attr(self): print(self.attr1) s = Student(111,222) s.get_attr() # 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__, # 在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问 class Student(object): def __init__(self, attr1, attr2): self.attr1 = attr1 self.__attr2 = attr2 pass s = Student(111,222) print(s.attr1) print(s.__attr2) #继承和多态 继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写 class Parent(): def say(self): print('i am parent') # 继承 class child(Parent): pass c = child() c.say() # 多态 子类覆盖了父类的同名方法 class child2(Parent): def say(self): print('i am child') c2 = child2() c2.say() # type print(type(123)) print(type(123) == type(456)) # True print(type(123) == int) # True print(type('123')) # <class 'str'> # isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上 class Hello(object): pass print(isinstance(Hello, object)) # True #类似__xxx__的属性和方法在Python中都是有特殊用途的, # 比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度, # 实际上,在len()函数内部,它自动去调用该对象的__len__()方法 # 下面两个等价 print(len('123')) print('123'.__len__()) #不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性 class Hello(object): name = 'hello' pass h = Hello() print(h.name) # hello h.name = 'world' print(Hello.name) # hello 类属性 print(h.name) # world 实例属性,屏蔽了类属性 del h.name print(h.name) # hello 实例属性 print(Hello.name) # hello 类属性 __slots__ 限制给类的实例添加属性 class Hello(object): __slots__ = ('name') # 实例智能添加name属性 pass h = Hello() h.name ='leyi' print(h.name) # leyi h.other = '123' # 会报错 print(h.other) # # @property装饰器就是负责把一个方法变成属性调用 class Hello(object): def __init__(self, name): self.name = name; h = Hello('leyi') print(h.name) # 实例可以随意修改类的属性,属性没经过校验,这样被认为不安全 h.name = 'xxx' print(h.name) # 为了控制属性,我们增加方法校验 class Hello2(object): def __init__(self, num = 0): pass def set_num(self, value): if not isinstance(value, int): raise ValueError('必须为数字类型') if value < 100 : raise ValueError('必须大于等于100') self.num = value def get_num(self): return self.num pass h2 = Hello2() h2.set_num(121) print(h2.get_num()) # 使用property 装饰器简化 class Hello3(object): def __init__(self, n = 0): pass @property # 将下面的方法转换成属性 def num(self): return self.n # @property本身又创建了另一个装饰器@score.setter,负责把一个setter方法变成属性赋值 @num.setter def num(self,value): if not isinstance(value, int): raise ValueError('必须为数字类型') if value < 100: raise ValueError('必须大于等于100') self.n = value @property # 不定义setter的话,属性就是只读属性 def num2(self): return self.n *12 h3 = Hello3() h3.num = 111 # 赋值 print(h3.num) # 取属性 # h3.num2 = 3333 # 因为是只读属性,所以赋值会报错 print(h3.num2) # 取属性 logging \ assert # 文件读写时都有可能产生IOError,一旦出错, # 后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件, # 我们可以使用try ... finally来实现 try : f = open('./b.txt') print(f.read()) finally : if f: f.close() # Python引入了with语句来自动帮我们调用close()方法 with open('./b.txt', 'r') as f1: print(f1.read()) # 如果文件很小,read()一次性读取最方便;如果不能确定文件大小, # 反复调用read(size)比较保险;如果是配置文件,调用readlines()最方便 # 反复调用read def readLines(): pos = 0 while True : with open('./b.txt', 'r') as f2: f2.seek(pos) data = f2.read(4) # 反复调用readline()也不错 if data: pos = f2.tell() yield data else: return for i in readLines(): print(i) # 读取所有行 with open('./b.txt', 'r') as f3: for l in f3.readlines(): print(l)