面向对象编程
必知:Python中有两种编程方式:
1.函数式编程
2.面向对象编程: 其实就是对类和对象的应用
1.类的创建:
格式:
class 类名: def 方法名():
2.类中方法的调用:
1.定义好一个类后
2.将类赋值给一个自定义的对象
3.利用自定义的对象来调用类中的方法
示例:
class bar: # 定义一个类 def foo(self): # 定义一个方法 print('hello world ') # 以上就是完成类的创建了 # 下面是对类中方法的调用 obj = bar() # 自定义一个对象,将类名加括号赋值给对象 obj.foo() # 通过'对象.方法名'的方式来调用
3.类中默认的__init__方法(构造方法):
当你执行将类名赋值给对象是,Python内部自动执行的一个函数,所以进行封装时也可以利用这个方法,可以让你的代码看起来更漂亮
方法中的默认self参数:
self参数Python内部在你调用方法的时候,自动传值的参数,其实他代指的是调用方法的对象的名字(也就是上面例子中的obj对象)
4.面向对象的三大特性:
1.封装:
1.就是当你的函数的参数中有许多的共同且不变的参数时,可以直接将值封装在对象中
2.利用类的特性,__init__方法,在方法中封装公用的值
class bar: def __init__(self, name, age): self.name = name self.age = age self.blood = 'o' def show_info(self, hobby): print(self.name, self.age, self.blood, hobby) alex = bar('alex', 15) alex.show_info('jklsjdfljk')
2.继承(可以多代继承)
子代可以继承父代类中的方法
示例:
class bar: # 父类(基类) def show_name(self): print('hello') def show_age(self): print('world') class car(bar): # 子类(派生类) def show_sex(self): print('male')
实现不继承父代中的方法:
代码示例:
class bar: def show_name(self): print('hello') def show_age(self): print('world') class car(bar): def show_sex(self): print('male') def show_name(self): # 在子代中定义一个和父代中相同名字的方法,就可以实现,方法重写 print('female')
执行父类中的已经被子类重写的方法:
1.super(父类类名, 当前对象).方法名
2.父类名.方法名(self)
注意:
1.self永远是执行该方法的调用者
2.Python中支持多继承
3.调用顺序
1.如果有init方法,最先执行init方法
2.父类从左到右
3.如果父类还有父类的话,就直接找到低,再找下一个父类
4.如果,不同的父类,有相同的基类的时候,最后执行基类
3.多态
Python原生就是多态的
类中的字段和方法:
字段:
普通字段:属于对象,只能通过对象来访问
静态字段:属于类,并且在内存中只存在一份,不但能通过对象来访问,还能通过类来调用(可以修改)
class bar: name = 'alex' bar.name = 'alvin' # 可修改 print(bar.name)
方法:
普通方法:保存在类中,只能通过对象来调用
class bar: def func(self): # 普通方法 print('hello world') obj = bar() obj.func()
静态方法:就是给普通的方法加上一个装饰器(staticmethod),这个方法就可以通过类直接调用,省去了创建对象的内存,还省略了self参数
class bar: @staticmethod def func(): # 静态方法 print('hello world') bar.func() # 直接由类调用方法
类方法:也是保存在类中,也是需要加上一个装饰器(classmethod),这个方法可以有self参数,但是默认不写成self而是写成cls,cal --->类名(Python自动传入这个参数)
· 各种方法的使用场景:
如果对象中需要保存一些值,执行某功能的时候,需要使用对象中的值,那么这时候我们就应该使用普通方法
如果时对象中不是必须保存一些值,我们就可以使用静态方法,使用静态方法的好处就是可以节省创建对象的空间
属性:
他是一个方法,需要加装饰器(property)他的创建方式和普通的方法的创建方式是一样的,并且调用方法是和字段一样的,
1.创建一个属性
class bar: @property def fun(self): # 这种方法叫做属性 print('hello world') return 'sdkfj' obj = bar() print(obj.fun)
2.修改属性的返回值
再创建一个方法,加上装饰器(属性名.setter),修改属性的返回值,需要在方法中添加一个接受修改以后的返回值
class bar: @property # 属性 def foo(self): return 1 @foo.setter # 对属性的返回值进行修改 def foo(self, value): # 需要有一个参数来接受,修改后的值 print(value) obj = bar() # 创建对象 obj.foo = 3 # 修改返回值
3.删除属性的返回值
再创建一个方法,加上装饰器(属性名.deleter), 删除属性的返回值
class bar: @property def foo(self): print('hello world') return 3 @foo.deleter def foo(self): # 创建一个新的方法,加上装饰器,可以删除之前的属性的返回值 return 1 obj = bar() del obj.foo # 删除属性的返回值
反射:
作用: 通过字符串的方式,操作对象中的成员
注意:类是一个对象,对象是一个对象,一个模块相对于函数也是一个对象,所以反射中的方法在类,模块中也都可以使用
反射提供的方法:
1.getattr(对象, 字符串类的成员) 利用字符串查看成员的值
2.hasattr(对象, 字符串类的成员) 查看对象中是否有这个成员,返回布尔值
3.setattr(对象, 成员名, 成员名的值) 在对象中创建新的成员
4.delattr(对象, 字符串类的成员) 删除对象中的成员
示例:
class bar: def __init__(self, name, age): self.name = name self.age = age # def func(self): # print('hello world') obj = bar('alex', 34) while True: your_enter = input('your enter:') # result = getattr(obj, your_enter) # getattr 的应用 # result = hasattr(obj, your_enter) # hasattr 的应用,判断后面的成员是否在前面的对象中,返回布尔值 result = delattr(obj, your_enter) # 利用delattr删除对象中的成员 res = getattr(obj, your_enter) # 这一段代码是判断是否正真的删除成员了 print(res)
单例模式:
单例模式的目的就是永远使用同一个实例(或者说是对象)
示例:
class bar: __v = None @classmethod def only_type(cls): # 使用类方法 if cls.__v : return cls.__v # 永远都是这一个实例 else: cls.__v = bar() # 实例化过程,创建了一个对象 return cls.__v def func(self): print('ksdfl') obj = bar.only_type() # 如果是需要使用单例模式,就这样进行实例化