两种编程方式:
- 面向过程和面向对象,从函数角度,面向过程即为无返回结果,面向对象即为有返回结果。
- 面向对象:类和对象
- **类:**一种抽象的概念,用来创建对象,类名要使用大驼峰命名法,其中包含类的属性和方法。属性是指类的特征,方法指的是类所具有的行为。
- **对象:**通过类进行创建的具体存在。在开发中,先有类后又对象。用类创建的对象拥有和该类相同的属性和方法。对象也叫类的实例。创建对象的过程叫做实例化,对象的属性叫做实例属性,对象调用的方法叫做实例方法。
- dir内置函数
def info(name,gender=True): print(name) print(gender) info("wang") print(dir(info))
6. 创建类和对象的示例
# 创建类
# 类名:大驼峰命名法
class demo:
# 方法的第一个参数必须是self
def color(self):
print("颜色是红色!")
def action(self):
print("唱跳rap篮球!")
# 创建对象
obj_demo = demo()
obj_demo.action()
- 可以给对象增加属性,不改变原类和其他对象的状态,不推荐使用;
# 创建类
# 类名:大驼峰命名法
class demo:
# 方法的第一个参数必须是self
def color(self):
print("颜色是红色!")
def action(self):
print("唱跳rap篮球!")
# 创建对象
obj_demo = demo()
obj_demo.name = "suyuan"
obj_demo.action()
print(obj_demo.name)
- 方法中的self,是哪个对象调用的方法,self就是哪个对象的引用。在方法内部,可以使用self调用该对象的属性或者该对象的其他方法。
# 创建类
# 类名:大驼峰命名法
class demo:
# 方法的第一个参数必须是self,在方法内部,可以使用self调用该对象的属性或者该对象的其他方法。
def color(self):
print("%s的颜色是红色!" % self.name)
def action(self):
print("唱跳rap篮球!")
# 创建对象
obj_demo = demo()
obj_demo.name = "suyuan"
obj_demo.color()
- 初始化方法(__init()__)
可以用来初始化方法的改造,让创建对象更加灵活。在初始化方法中设置属性。
# 创建类
# 类名:大驼峰命名法
class Demo:
# 在初始化方法中设置类的属性(常用方法)
def __init__(self):
# 注意在定义属性时,要使用self.进行定义
self.name = "suyuan"
# 方法的第一个参数必须是self,在方法内部,可以使用self调用该对象的属性或者该对象的其他方法。
def color(self):
# 调用其他方法中的属性时,也要使用self.
print("%s的颜色是红色!" % self.name)
def action(self):
print("唱跳rap篮球!")
# 创建对象
obj_demo = demo()
print(obj_demo.name)
obj_demo.color()
- 使用参数设置属性值
# 创建类
# 类名:大驼峰命名法
class demo:
# 在初始化方法中设置类的属性(常用方法),并且可以通过参数传递的方法传递参数
def __init__(self,name):
self.name = name
# 方法的第一个参数必须是self,在方法内部,可以使用self调用该对象的属性或者该对象的其他方法。
def color(self):
print("%s的颜色是红色!" % self.name)
def action(self):
print("唱跳rap篮球!")
# 创建对象
obj_demo = demo("wangyuechuan")
print(obj_demo.name)
obj_demo.color()
- 销毁(__del()__)内置方法
为对象分配完空间后,自动调用初始化方法;
在一个对象在内存中被销毁前,会自动调用该销毁方法。在程序中如果该对象是一个全局变量,那么在程序最后会执行销毁方法。如果想提前执行那就需要使用del()关键字。 - str、repr内置方法
在python中,如果使用print直接输出对象,那么会执行该对象的全部属性和方法,同时输出该对象在内存中的地址。如果只想输出用户自定义的内容,那在类中增加__str()__方法即可,但是需要注意str内置方法必须通过return返回一个字符串。str主要是返回用户看到的字符串(利用print)。
repr和str类似,但是repr返回的是调试人员调试的字符串; - iter内置方法:
如果一个类想使用for进行循环遍历,则必须使用_iter_()方法; - 使用枚举类的方法:使得每一个常量都是class的一个唯一的实例。Enum,@unique装饰器可以帮助我们检查保证没有重复值。
访问这些枚举类型可以有很多方法:from enum import Enum, unique class Gender(Enum): Male = 0 Female = 1
Gender.Male # 返回值依旧是Gender.Male
Gender.Male.value # 返回是Male对应得序列号
Gender(index) # index是序列号,返回值是序列号对应得Gender.Male
需要注意枚举类型不可以实例化 - 面向对象的三大特性:
封装:根据职责将属性和方法封装到抽象的类当中。
继承:实现代码的重用,不需要重复的定义。
多态:不同的对象调用相同的类,得到不同的执行效果,增加代码的灵活度。 - 继承:子类拥有父类的所有属性和方法。并且子类拥有特有的属性和方法
class People:
def eat(self):
print("他会吃")
def run(self):
print("他会跑")
# 子类继承父类的语法
class YueChuan(people):
def success(self):
print("他会喝水")
zhangsan = People()
lisi = YueChuan()
专业术语:
子类—派生类
父类—基类
继承—派生
继承具有传递性,可以不断向下穿继承。
- 当父类的属性和方法不符合子类需求时,可以对相关属性和方法进行重写。重写有两种情况,其一是对原有的拓展,其二是对原有的重写。
- 重写的实现方法就是在子类中定义一个与父类相关属性方法同名的并且进行程序重写即可。重写后,通过子类封装的对象只会调用在子类中重写的方法,而不会调用父类中相对应的方法。
- 拓展的实现方法就是在子类中定义一个与父类相关方法同名的方法,并在在该方法中,使用super().父类方法名。
class people:
def eat(self):
print("他会吃")
def run(self):
print("他会跑")
# 子类继承父类的语法
class yuechuan(people):
def success(self):
print("他会喝水")
def eat(self):
super().eat()
print("对父类方法进行拓展")
zhangsan = people()
lisi = yuechuan()
zhangsan.eat()
lisi.eat()
- 私有属性和私有方法:
私有命名方法:在名字前加__即可以构成私有,在外界不能直接调用该私有属性或私有方法。即私有属性和私有方法不能被继承或者不能被其对象直接调用。外部属性在外部不能被修改,如果需要修改则可以使用方法传入参数,在类的定义中进行修改,这种方法一般用于对参数做检查,避免传入无效的参数。 - 通过公有方法间接访问父类的私有方法或者私有属性
class People: def __init__(self): # 要注意定义以及调用属性的格式 self.__num1 = 10 def eat(self): print("他会吃") def __run(self): print("他会跑") def gongyou(self): print("间接调用私有方法和私有属性 %d" % self.__num1) # 子类继承父类的语法 class YueChuan(People): def success(self): print("他会喝水") def eat(self): super().eat() print("对父类方法进行拓展") zhangsan = People() zhangsan.gongyou() lisi = YueChuan()
- 继承:单继承和多继承。多继承即为一个子类继承多个父类。
# 多继承需要注意,不同父类要避免出现同名字的方法或者属性 class Father: def demo1(self): print("继承父亲") class Mother: def demo2(self): print("继承母亲") class Son(Father,Mother): pass zhangsan = Son() zhangsan.demo1() zhangsan.demo2()
- python的内置属性(_mro_):用来查看子类的继承顺序
print(Son.__mro__)
- 新式类和旧式类:
新式类是继承自object的类,推荐使用。class Demo(object): pass
- 多态:不同的子类对象调用相同的父类方法,产生不同的执行结果。多态是以继承和重写父类方法为基础的。
class Dog(object): # 使用类封装对象时,封装的参数必须要和__init__函数的参数一致 def __init__(self,name): self.name = name def game(self): print("玩耍!") class XiaoTianDog(Dog): def game(self): print("在天上玩耍!") class People(object): def __init__(self,name): self.name = name def game(self,Dog): print("%s 陪 %s 玩耍" % (self.name , Dog.name)) # 使用类封装对象时,封装的参数必须要和__init__函数的参数一致 dog = Dog("旺财") fly_dog = XiaoTianDog("哮天犬") xiaoming = People("xiaoming") # 不同的子对象调用相同的父类产生不同的结果 xiaoming.game(fly_dog) xiaoming.game(dog)
- 每个对象都有自己独立的内存空间保存各自不同的属性。多个对象的方法在内存中只有一份。在调用方法时,需要把对象的引用传递到方法的内部。
- 类对象和实例对象:类是一个特殊的对象,被称为类对象,在内存空间内仅有一份,在其内有类属性和类方法以及静态方法,其中类方法是为了间接调用类属性。如果某个方法需要访问实例属性,则将其封装为实例方法,如果该方法不需要访问实例属性而需要访问类属性,则将其封装为类方法。如果该方法不需要访问实例属性和类属性,则将其定义为静态方法。
- 类属性:在类定义中直接使用赋值语句即可,用来存储一些属于类的特征和对象无关,例如记录该类被调用的次数。
属性的获取机制:向上查找机制,如果使用对象.属性进行属性的调用,那会首先检测再对象内部有没有该属性,如果没有则才会调用类属性。class Dog(object): count = 0 # 使用类封装对象时,封装的参数必须要和__init__函数的参数一致 def __init__(self,name): self.name = name # 类属性,在此处要注意不能使用self.,因为self.表示对象的引用。 # 类属性是记录和类相关特征的,和对象无关,所以不能用self. Dog.count += 1 def game(self): print("玩耍!") class XiaoTianDog(Dog): def game(self): print("在天上玩耍!") class People(object): def __init__(self,name): self.name = name def game(self,Dog): print("%s 陪 %s 玩耍" % (self.name , Dog.name)) # 使用类封装对象时,封装的参数必须要和__init__函数的参数一致 dog = Dog("旺财") fly_dog = XiaoTianDog("哮天犬") xiaoming = People("xiaoming") # 不同的子对象调用相同的父类产生不同的结果 xiaoming.game(fly_dog) xiaoming.game(dog) print(Dog.count)
使用对象.类属性 = 值,不会改变该类属性的值,本质上是定义了一个对象属性。 - 类方法
1、第一个参数必须要cls
2、在def上一行要写:@classmethon
3、类方法也可以被对象所引用。
- 静态方法:
@staticmethod
不需要指定第一个参数,不需要创建对象通过对象调用。通过类名.静态方法名调用。
- 单例设计模式
目的:让类创建的对象在系统中只有唯一一个实例。每一次执行类名()返回的是同一个地址。
策略:object基类提供了一个内置的静态方法_new_,该方法的作用是为对象分配内存空间,并且返回对象的引用,返回的对象引用将会传递到初始化方法的第一个参数,从而实现对象初始化和对象属性定义。如果要使用单例设计模式,则需要改造该内置静态方法。
示例:class MusicPlayer(object): # 定义类属性,用来记录该类被调用的次数(需要注意,在调用类时,并不是类中的每个属性和方法都会执行) address = None # 内置的静态类方法 def __new__(cls, *args, **kwargs): # 改写方法需要调用原方法,进行对象空间的分配,需要注意__new__是类方法,需要引用cls if cls.address is None: # 且需要注意,super().后方法的参数,new需要而init不需要 cls.address = super().__new__(cls) return cls.address player1 = MusicPlayer() player2 = MusicPlayer() print(player1) print(player1)
- 内置函数super的使用:
- 对对象的属性进行操作: getattr()、setattr()以及hasattr()
- python的动态语言特性:可以在程序的运行过程中动态的加入一些功能,使用进行def定义;例如给类绑定新的属性,虽然在pycharm中通过对象调用新的属性不会提醒,但仍然可以执行。出于安全等原因,为了限制给类及其对应的对象绑定新的属性,所以可以使用__slots__ == (限制的属性内容);
- 通常,我们在类中定一个get分数的方法和set分数的方法,但是这种方法在使用的时候略显繁琐,一般想直接使用对象.属性进行定义或者访问。虽然也可以在类中直接定义该属性,但是这样就无法对属性的赋值等进行筛选。而筛选一般可以使用装饰器,和类再进行结合,这时就需要将方法变为属性(装饰器:@property)
"""使用装饰器将方法变为属性:请利用@ property给一个Screen对象加上width和height属性,以及一个只读属性resolution:""" class Screen(): @ property def width(self): return self.__width # 必须要加上这个双下划线 @ width.setter def width(self, value): if isinstance(value, int): self.__width = value else: raise ValueError("Not int") @property def height(self): return self.__height @height.setter def height(self, value): if isinstance(value, int): self.__height = value else: print("Please input the width(int)!") # 定义只读属性 @ property def resolution(self): return self.width * self.height tree = Screen() tree.height = 10 tree.width = 20 print(tree.resolution)
- 实例属性和类属性:
- 给实例绑定属性:在类中的__init__使用self.
- 类本身定义属性:在类中直接定义(形如定义变量);类属性可以用来记录类被调用的次数
- 给实例定义属性:在程序中使用对象.进行定义
- 如果实例属性和类属性名字相同,则实例属性会覆盖类属性,但是如果重新使用类调用该属性,该属性值任然是类中定义的内容。
- 异常:
异常捕获:程序在运行时,如果解释器遇到错误,则会停止程序运行并提示错误信息,这个动作称为抛出异常,但在程序编写时,很难面面俱到,一般通过异常捕获的方式进行统一处理。
错误类型捕获:python解释器抛出异常时,异常信息最后一行的第一个单词就是异常的类型。这时就可以对不同的异常进行针对化的处理。在程序中错误类型放在except之后:while True: try: # 可能会出现错误的代码 num = int(input("请输入一个整数!")) print(num) break # 如果出现错误需要的处理 except: print("输入错误,请输入一个整数!")
捕获未知错误:要预判所有可能出现的错误有些难度,如果想让程序不会因为任何抛出异常而系统运行终止,则要增加一个exceptwhile True: try: # 可能会出现错误的代码 num = int(input("请输入一个整数!")) print(8/num) break # 如果出现错误需要的处理 except ValueError: print("输入的不是整数,请输入一个整数!") except ZeroDivisionError: print("请输入一个非零的整数!")
异常处理的完整语法:while True: try: # 可能会出现错误的代码 num = int(input("请输入一个整数!")) print(8/num) break # 如果出现错误需要的处理 except ValueError: print("输入的不是整数,请输入一个整数!") except Exception as result: print("%s,请输入一个整数!" % result)
异常的传递性:在函数中出现异常,不会直接抛出异常使程序终止,而是一层层将异常传递,直至在主程序中如果依旧没有处理,则才会抛出。这样可以有效地缩减代码大小,防止抛出异常的冗余。
抛出raise异常:在程序开发中,如果代码错误系统会抛出异常,同时也可以通过特定的业务需求主动的抛出异常。在python中提供了一个Exception异常类,主动抛出异常步骤如下:- 创建Exception异常对象
- 使用raise抛出异常对象
def passinput(): password = input("请输入长度为8的密码!") if len(password) >= 8: return password # 创建一个异常对象,类的参数为“异常类型” ex = Exception("输入的密码长度不够!(%s)" % len(password)) # 使用raise关键字抛出异常 raise ex # 捕获异常 try: password = passinput() except Exception as result: print("异常类型为:%s" % result) # 如果没有异常,执行的代码 else: print("没有异常,密码为:%s" % password) # 无论如何,都会执行的代码! finally: print("程序执行完成!")
- 多态和多态性
- 多态:一类事物具有多种形态,多态的概念一览与继承;
- 多态性:具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。多态性本质是是一种接口函数;多太细增加了程序的灵活性和可扩展性。
- 正则表达式:sohu.com/a/296122577_120050566