两大编程思想
两大编程思想:面向过程、面向对象
用西红柿炒鸡蛋举个例子:
面向过程:事物比较简单,可以用线性思维去解决。【1、打鸡蛋;2、切西红柿;3、点火;4、倒油;5、下鸡蛋;6、下西红柿;7、翻炒3分钟;8、出锅。】
面向对象:事物比较复杂,使用简单的线性无法解决。【找一个餐馆,点一份西红柿炒鸡蛋】
共同点:解决实际问题的一种思维方式。
二者相辅相成,并不是对立的。
解决复杂问题,通过面向对象方式便于我们从宏观上把握事物之间的关系,方便我们分析整个系统具体到微观操作,仍然使用面向过程的方式来处理。
类与对象
类:类别,分门别类,多个类似事物组成的群体的统称,能够帮我们快速理解和判断事物的性质。
对象:100、99、500都是int类下包含的相似的不同个例、实例或者对象。
python中一切皆对象
类的创建
类的创建格式
class 类名:
pass
注意:类名建议以下列格式为准,每个单词的首字母大写,其他小写,比如:StudentInfo
类的组成
类的组成有:类属性、实例方法、静态方法、类方法、初始化方法、实例属性。
类属性—直接写在类中的变量。
实例方法—def est(self): pass
静态方法— @staticmethod def method(): pass
类方法—@classmethod def cml(cls): pass
初始化方法-- def init(self): pass
实例属性—就是定义在__init__方法中的变量;
class Student(object):
# 类属性
studentType = '学生'
#初始化方法
def __init__(self, name, age):
#name age是实例属性
self.name = name
self.age = age
@staticmethod
def staticMethodInfo():
print('我是静态方法')
@classmethod
def classMethodInfo(cls):
print('我是类方法')
def est(self):
print("我是实例方法")
对象的创建
对象的创建,即类的实例化
格式:实例名 = 类名()
调用类中的属性【类属性、实例属性】以及方法【静态方法、实例方法、类方法】
格式:实例名.属性/方法
类属性:类中方法外的变量,被该类的所有对象所共享。
类方法:使用classmethod修饰的方法,使用类名直接调用。
静态方法:使用staticmethod修饰的方法,使用类名直接调用。
例子如下:
class Student(object):
# 类属性
studentType = '学生'
#初始化方法
def __init__(self, name, age):
print('我是初始化方法')
#name age是实例属性
self.name = name
self.age = age
@staticmethod
def staticMethodInfo():
print('我是静态方法')
@classmethod
def classMethodInfo(cls):
print('我是类方法')
def eat(self):
print("我是实例方法")
# 创建实例时会调用初始化方法
stu = Student('张三',23) # 我是初始化方法
#调用静态方法
Student.staticMethodInfo() # 我是静态方法
stu.staticMethodInfo() # 我是静态方法
#调用类方法
Student.classMethodInfo() # 我是类方法
stu.classMethodInfo() # 我是类方法
#调用实例方法
# Student.eat() #报错,TypeError: eat() missing 1 required positional argument: 'self'
stu.eat() # 我是实例方法
#访问类属性
print(Student.studentType) # 学生
print(stu.studentType) # 学生
#访问实例属性
# print(Student.name) #报错,AttributeError: type object 'Student' has no attribute 'name'
print(stu.name) # 张三
动态绑定属性和方法
Python是动态语言,在创建对象之后,可以动态地绑定属性和方法。
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
stu = Student('张三',20)
stu.gender = '女'
print(stu.gender) # 女
def show():
print('show方法')
stu.show = show
stu.show() # show方法
封装
封装:提高程序安全性。
将数据和行为包装到到类对象中,在方法内部对属性进行操作,在类的外部调用方法,这样,无需关心方法内部的具体实现细节,从而隔离了复杂性。
属性私有:__name = ‘xxxx’
继承
继承:提高代码的复用性。
格式:
class 子类名(父类1,父类2):
pass
如果一个类没有继承任何类,则默认继承object类。
python支持多继承。
定义子类时,必须在其构造函数中调用父类的构造方法:super().init()
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade
per = Person('大明',56)
print(per.age) # 56
print(per.name) # 大明
stu = Student('小明',23,100)
print(stu.name) # 小明
print(stu.age) # 23
print(stu.grade) # 100
方法重写
如果子类对继承自父类的某个属性或方法不满意,可以在子类中对其进行重新编写。子类重写后的方法中可以通过super().xx()调用父类中被重写的方法。
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def printInfo(self):
print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self.grade = grade
#方法重写
def printInfo(self):
super().printInfo()
print('我还是个学生,'+str(self.grade))
per = Person('大明',56)
stu = Student('小明',23,100)
per.printInfo()
stu.printInfo()
object类
object类是所有类的父类,因此所有类都有object类的属性和方法。
内置函数dir()可以查看指定对象所有属性。
object有一个__str__()方法用于返回一个对于’对象的描述’,对应内置函数str(),经常用于print()方帮我们查看对象的信息,所有我们经常会对__str__()进行重写。
print(dir(object))
print(object)
print(str(object))
# ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
# <class 'object'>
# <class 'object'>
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def printInfo(self):
print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')
per = Person('大明',56)
print(dir(Person))
print(Person)
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'printInfo']
# <class '__main__.Person'>
print(per) # <__main__.Person object at 0x000001A3ACDC8358>
print(dir(per)) #实例对象比类中多了实例属性
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age', 'name', 'printInfo']
class Person1:
def __init__(self,name,age):
self.name = name
self.age = age
def printInfo(self):
print('我叫'+str(self.name)+',今年'+str(self.age)+'岁了')
#重写str方法
def __str__(self):
super().__str__()
print('打印Person类的信息')
return 'Person1'
print(Person1('11',34))
# 打印Person类的信息
# Person1
多态
多态具有多种形态,即使不知道一个变量所引用的对象到底是什么类型,任然可以通过这个变量调用方法,在运行过程中根据变量所引用对象的类型,动态决定调用哪个对象中的方法。
class Person:
def eat(self):
print('Person eat')
class Animal:
def eat(self):
print("Animal eat")
class Dog(Animal):
def eat(self):
print("Dog eat")
class Cat(Animal):
def eat(self):
print("Cat eat")
def fun(classObject):
classObject.eat()
p = Person()
fun(p) # Person eat
a = Animal()
fun(a) # Animal eat
d = Dog()
fun(d) # Dog eat
c = Cat()
fun(c) # Cat eat
注意:静态语言和动态语言关于动态的区别:
静态语言实现多态的三个必要条件:继承、方法重写、父类引用指向子类对象。
动态语言的多态崇尚"鸭子类型",在鸭子类型中不需要关心对象是什么类型,到底是不是鸭子,只关心对象的行为。
特殊方法和特殊属性
特殊属性
-------A ----- B
| | |
D C = C
实例x
- dict—获取类对象和实例对象所绑定的所有属性和方法
- x.class–输出实例对象所属的类
- C.bases:输出C类父类(A|B)
- C.base----输出C类第一个父类(A)
- C.mro-----类的层次关系;
- A.subclasses()----A类的子类列表(D,C)
class A:
pass
class B:
pass
class D(A):
pass
class C(A,B):
pass
c = C()
print(A.__dict__)
#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
# <class '__main__.C'>
print(c.__class__) # <class '__main__.C'>
print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>)
print(C.__base__) # <class '__main__.A'>
print(C.__mro__) # (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
print(A.__subclasses__()) # [<class '__main__.D'>, <class '__main__.C'>]
特殊方法
- len()–通过重写__len__()方法让内置函数len()的参数可以是自定义类型。
- add()–通过重写__add__()方法,可以使用自定义对象具有+的功能。
- new()—用于创建对象。
- init()----对创建的对象进行初始化。
类的浅拷贝与深拷贝
变量的赋值操作只是形成两个变量,实际上还是指向同一个对象。
浅拷贝:Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝。
深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,原对象和拷贝对象所有的子对象也不相同。
class Person:
def __init__(self,name,age) -> None:
self.name = name
self.age = age
# 浅拷贝
p = Person('小明',23)
p1 = p
print(id(p)) # 2538254986824
print(id(p1)) # 2538254986824
#实例p和实例p1的指向的内存地址是一样
#深拷贝
from copy import deepcopy
p2 = deepcopy(p)
print(id(p)) # 2536288185648
print(id(p2)) # 2536288322392
#实例p和实例p1的指向的内存地址是不一样,不是同一个内存地址。

被折叠的 条评论
为什么被折叠?



