面向对象编程:Object Oriented Programming,简称OOP,是一种程序设计方法。
术语 | 概念及介绍 |
---|---|
类(Class) | 用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对 象所共有的属性和方法。其中的对象被称作类的实例。 |
实例 | 也称对象。通过类定义的初始化方法,赋予具体的值,成为一个"有血有肉 的实体"。 |
实例化 | 创建类的实例的过程或操作。 |
实例变量 | 定义在实例中的变量,只作用于当前实例。 |
类变量 | 类变量是所有实例公有的变量。类变量定义在类中,但在方法体之外。 |
数据成员 | 类变量、实例变量、方法、类方法、静态方法和属性等的统称。 |
方法 | 类中定义的函数 |
静态方法 | 不需要实例化就可以由类执行的方法 |
类方法 | 类方法是将类本身作为对象进行操作的方法。 |
方法重写 | 如果从父类继承的方法不能满足子类的需求,可以对父类的方法 进行改写,这个过程也称override。 |
封装 | 将内部实现包裹起来,对外透明,提供api接口进行调用的机制。 |
继承 | 即一个派生类(derived class)继承父类(base class)的变量和方法。 |
多态 | 根据对象类型的不同以不同的方式进行处理。 |
面向过程:根据业务逻辑从上到下写代码
面向对象:将数据与函数绑定到一起,进行封装。减少重复代码的重写过程
示例1:面向过程
def stu_info(name,age,gender):
print(name,age,gender)
stu_info("oldli","18","male")
stu_info("ellen","18","male")
stu_info("bruin","18","male")
示例2:面向对象
class Students(object):
def stu_info(self,name, age, gender):
print(name, age, gender)
s = Students()
s.stu_info("oldli","18","male")
s.stu_info("ellen","18","male")
s.stu_info("bruin","18","male")
类是抽象的模板,用来描述具有相同属性和方法的对象的集合,比如 Animal类。
类名通常采用驼峰式命名,尽量让字面意思体现出类的作用。
Python使用class关键字来定义类,结构如下:
class 类名(object): # object 可有可无
def 方法名(self,参数): # 行为
pass
name = 类名() # 定义一个实例对象
name.方法名(参数) # 调用
self 形参
self 是对象本身,也就是说,当创建的对象是谁时,self就是谁
class Student(object):
def test(self):
# print(self)
pass
oldli = Student() # 实例化对象
print(oldli)
oldli.test()
Chy = Student() # 实例化对象
print(Chy)
Chy.test() # 调用类
# 输出结果
#<__main__.Student object at 0x03955190>
#<__main__.Student object at 0x039552C8>
class Student(object):
def info(self):
print(self.name,self.age)
marshal = Student()
marshal.name = "marshal"
marshal.age = "18"
# print(marshal)
marshal.info() # 输出结果 marshl 18
xiaoming = Student() # 实例化对象
xiaoming.name = "xiaoming"
xiaoming.age = "22"
# print(marshal)
xiaoming.info() # 输出结果 xiaoming 22
class Students(object):
def stu_info(self,name):
print(name, self.age, self.gender)
s = Students() # 实例化对象
s.age = "18"
s.gender = "male"
s.stu_info("oldli")
s.stu_info("ellen")
s.stu_info("bruin")
'''
输出结果:
oldli 18 male
ellen 18 male
bruin 18 male
'''
# 构造方法(初始化方法)
def __init__(self):
pass
# 特殊意义
创建对象的同时,通过对象执行这样的一个方法,叫做构造方法
class students(object):
def __init__(self,age,gender):
#属性
self.age = age
self.gender = gender
self.addr = "ChongQing"
# 打印信息
def stu_info(self,name):
print(name,self.age,self.gender,self.addr)
s = students() # 实例化对象
s.stu_info("oldli")
s.stu_info("enlen")
s.stu_info("bruin")
# 输出结果:
# oldli 18 male ChangSha
# ellen 18 male ChangSha
# bruin 18 male ChangSha
tips: 使用了该函数,一定返回字符串;如果返回出错,可以
定义的 str
def __str__(self):
pass
# 1. return 关键字 将我们的信息直接返回对象
# 2. 只能时str 如果非字符串 str() 强转
class People(object):
def __init__(self):
self.age = 18
self.name = "zero"
self.hobby = "play game"
def __str__(self):
return str({
"name":self.name,"age":self.age})
# return 返回的多个值 元组
# 一定返回字符串
zero = People()
print(zero) # 输出结果: {'name':'zero',
‘’‘只有当年龄>0的时候才返回出来,否则默认为0岁’’’
class People(object):
def __init__(self): # 初始化参数
self.age = 0
def set_age(self,new_age): # 判断
if new_age >= 0 and new_age <=120:
self.age = new_age
elif new_age > 120:
self.age = 0
else:
# abs()取绝对值的内置方法
self.age = abs(new_age)
def get_age(self):
return self.age
xiaoming = People() # 实例化对象
xiaoming.set_age(10) # 调用函数
print(xiaoming.get_age())
# 输出结果为 10
在类中,不希望外部去访问我的属性。
格式:
# 私有属性 -->__属性名():
# 定义一个类
class People(object):
def __init__(self): # 初始化参数
self.__age = 18 # 私有属性,外部访问不了
self.name = zero
def get_age(self): # 可从内部调用私有属性
print(self.__age)
def set_age(self,age):
self.__age = age
zero = People() # 实例化对象
print(zero.name) # 打印取出名字 输出结果 zero
print(zero.__age) # 会报错,no attribute 。 不能直接从外部调用私有的属性(__age)
zero.get_age() # 调用get_age 方法获取私有属性 输出结果18
zero.set_age(22) # 重新传入参数
zero.get_age() # 输出结果 22
print(zero.__dir__()) # 查看对象的方法跟属性
定义私有方法
class Demo(object): # 定义一个类
def test1(self):
print("test1:)
def __test2(self):
print("test2")
d = Demo() # 实例化对象
d.test1() # 输出结果为 test1
d.__test2() # 报错,不能调用
class Province(object):
country = "中国" # 类属性, 静态属性 对象, 类来调用
def __init__(self,name):
self.name = name
def print_info(self):
print(Province.country,self.name) # 静态属性调用 类名.静态属性名
guangdong = Province("广东")
chongqing = Province("重庆")
guangdong.print_info() # 输出结果 中国广东
chongqing.print_info() # 输出结果 中国重庆
class Demo(object):
def __init__(self):
self.name = "zero"
def test(self):
print(self.name)
@staticmethod # 静态方法,等同于上面的
def test1(name):
print(name)
@classmethod
def class_md(cls):
print(cls)
d = Demo() # 实例化对象
d.test() # 输出结果 zero
Demo.test1("王先生") # 输出结果 王先生 调用了静态属性@staticmethod
d.test1("小周") # 输出结果 小周
Demo.class_md() #
import time
def show_time():
print(time.strftime("%H:%M:%S",time.localtime()))
show_time() # 输出结果, 当前时间
import time
class TimeTest(object):
@staticmethod
def show_time():
print(time.strftime("%H:%M:%S",time.localtime()))
nowtime = Timetest()
TimeTest.showtime() # 输出结果, 当前时间
可以将类的方法变为属性
class Demo(object):
def __init__(self):
self.name = "zero"
@property # 将方法变为属性
def test(self):
print(self.name)
return "test"
@test.setter # d.test = "456"
def test(self,nums):
print(nums)
@test.deleter
def test(self):
print(1111)
d = Demo() # 实例化对象
print(d.name)
res = d.test
print(res)
d.test = "456" # 想要改变
del d.test
class Page(object):
def __init__(self,current_page):
try:
p = int(current_page)
except Exception as e: # 万能异常捕获
p = 1
self.page = p
@property
def start(self):
start = (self.page-1)*10
return start
@property
def end(self):
end = self.page * 10
return end
li = list(range(100))
while True:
p = int(input("请输入要查看的页码:"))
page = page(p) # 实例化对象
print(li[page.start:page.end])
创建新类的方式,新类可以继承一个或者多个父类;
作用:避免重复造轮子
新式类 继承object
经典类 不继承object
tips:
如果调用的是继承的父类中的方法,可以在这个公有方法中访问父类中的私有属性和私有方法;
但是如果在子类中实现了一个公有方法,那么这个方法是不能够调用继承的父类中的私有方法和私有属性
class Father(object):
def __init__(self):
self.name = "amy"
self.__age = 18
def __test(self):
print("__test")
def test1(self):
print(self.__age)
class Son(Father):
# def __init__(self):
# print("Son")
# super().__init__()
def test3(self):
# print(self.__age)
self.__test()
def __test(self):
print("__test")
s = Son()
print(s.name) # amy
# print(s.__age) # 私有属性不会被继承
# s.__test() #私有方法不会被继承
# s.test1()
s.test3() # __test
class GrandFather(object):
def sleep(self):
print("睡10个小时")
class Father(GrandFather): # 父类 基类
def run(self):
print("我会跑")
def eat(self):
print("我会吃")
class Son(Father):
def study_python(self):
print("我学python")
s = Son()
# 子类没有, 就往父类中去找
s.run() # 输出结果 我会跑
s.study_python() # 输出结果 我学python
# 父类没有 就会往父类的父类中去找
s.sleep() # 输出结果 睡10个小时
示例:
class GrandFather(object):
def sleep(self):
print("GrangF睡觉")
class Father(GrandFather):
def run(self):
print("Father会跑")
class Father1(Father):
def run(self):
print("Father1会跑")
def sleep(self):
print("Father1睡觉")
class Son(Father,Father1):
pass
s = Son()
s.run()
s.sleep() # C3
# print(Son.__mro__) # 可以查看调用顺序
tips:
'''
重写的同时并且执行父类中的方法
'''
class GrandFather(object):
def sleep(self):
print("睡10个小时")
class Father(GrandFather):
def run(self):
print("我会跑")
def eat(self):
print("我会吃")
class Son(Father):
def study_python(self):
print("我学python")
def sleep(self):
print("我睡8个小时")
#super(Son,self).sleep() # 下面的完整版
super().sleep() # 效果同上
#GrandFather.sleep(self) # 效果同上
s = Son()
s.sleep() # 输出结果 我睡8个小时 睡10个小时
总结:
示例:
class Person(object):
def print_info(self):
print("我是个人")
class Girl(Person): # 继承
def print_info(self):
print("我是zero")
def info(travel): # 定义一个函数
travel.print_info()
zero = Person() # 实例化对象
info(zero) # 我是个人
zero1 = Girl() # 实例化对象
info(zero1) # 我是zero
# str()
# print(str().__doc__)
class Demo(object):
'''
我是Demo的注释
'''
'我有一个构造方法'
"我....."
def __init__(self):
pass
d = Demo()
print(d.__doc__) # 输出结果:我是demo的注释
class Demo:
def __del__(self):
print("好惨,我被回收了")
d = Demo()
d1 = d
print("-"*20)
del d
del d1
print("-"*20)
'''
输出结果:
--------------------
好惨,我被回收了
--------------------
'''
class Demo(object):
def __call__(self,*args,**kwargs):
print("我可以调用了哟")
d = Demo()
d() # 'Demo' object is not callable # 输出结果: 我可以被调用了哟
# str()
class Demo(object):
gender = "female"
def __init__(self):
self.name = "zero"
self.__age = 18
def test(self):
print("test")
d = Demo()
d.test()
print(d.__dict__) # dict 查看对象中的实例属性
print(Demo.__dict__) # 查看类中的成员 -->类属性与行为
print(d.__dir__()) # 列表 查看对象的 -->成员
print(Demo.__dir__(d))
print(d._Demo__age)
new 在类准备自身实例化时调用的
new 静态方法 创建对象
init 实例方法,对象自动调用的方法
class Demo(object):
def __init__(self):
print("__init__")
# 如果我们这个类中没有new,会创建对象的时候,会自动执行父类中的new方法
def __new__(cls,*args,**kwargs):
return super().__new__(cls) # 传入别的类名时,不会调用__init__方法
d = Demo()
# 1.创建对象 __new__
# 2.调用__init__方法
# 3.返回对象引用
永远只使用一份对象 (重点:记录日志在logger)
对象不存在时候 -->创建对象
对象存在 -->永远只返回当前创建对象
class Demo(object):
flag = None # 标志
# 创建对象 __new__
def __new__(cls,*args,**kwargs):
# return super().__new__(cls)
if cls.fflag is None:
cls.flag = super().__new__(cls):
return cls.flag
else:
return cls.flag
d = Demo()
print(id(d))
d1 = Demo()
print(id(d1)) # 输出两个相同的ID地址
getattr(py文件名,输入的名字)
getattr(views,ipt)