面向对象
面向对象编程是一种编程思想,他不像c语言那样(c语言是面向过程编程),面向对象编程为OOP编程(Object Oriented Programming)。
什么是面向对象?在世界上可以称为万物皆对象,比如你要吃个鱼香肉丝,你会怎么做,先去市场上卖鱼、买鱼料、回家洗鱼、开火做饭等等,这种思想就是面向过程,而面向对象则不会考虑这么对,会去饭店说,来个鱼香肉丝。假如你明天又想吃宫保鸡丁,面向过程就麻烦了,还需要再次装备,而面向对象就很简单了。
对象
类的实例称为对象。就是通过类创建出来的。
类
类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。
把类当成鸡,那么对象就是蛋
定义
-
class 类名:
- 属性
- 方法
- 属性
属性就是某个类、某个对象的特征、某些变量- 类属性
类属性就是可以在类的内部直接调用 - 对象属性
对象属性只能对象调用
- 类属性
- 方法
方法是某个类、或者某个对象的行为,也就是一些函数。- 普通方法:
-
定义格式:
def 方法名(self,参数1,参数2):
pass -
调用:
都要依赖对象调用方法
对象名.方法名(参数)
注意: 在调用过程中会默认传递self对象,self表示的是对象本身 -
方法中访问对象属性:
self.属性名
self.属性名= 值 ----》 改变对象属性的值 -
方法中访问普通方法:
self.方法名(参数)
-
- 类方法:
- 定义格式:
@classmethod
def 类方法名(cls,参数):
pass - 使用:
类名.方法名()
也可以通过:
对象.方法名() (了解)
- 定义格式:
- 静态方法:类似类方法
- 定义格式:
@staticmethod
def 方法名():
pass - 使用:
类名.方法名()
- 定义格式:
- 普通方法:
class Utils:
# 类属性
version = '1.0'
# 类方法
@classmethod
def conn_db(cls): # cls其实就是类对象本身
print('classmethod---->', cls)
print('加载数据库驱动程序,当前版本号是:', cls.version)
print('数据库建立连接成功!')
# cls.select_data()
@staticmethod
def select_data(): # 参数:不依赖对象self,也不依赖类cls
print('查询数据库的数据,当前版本号是:', Utils.version)
Utils.conn_db()
# Utils.conn_db() # 类方法的调用
# print('Utils:', Utils)
# # 类方法能否被对象调用? 能访问
#
# u = Utils()
# u.conn_db() # 对象调用conn_db(cls) --->cls仍然是<class '__main__.Utils'>
# print('u===:', u)
# 类方法方法中能否访问对象属性?
# 不能
# 静态方法的调用:
Utils.select_data()
# 静态方法能否被对象调用? 能访问
u = Utils()
u.select_data()
# 类方法中能否调用静态方法? 静态方法中能否调用类方法? 都可以
print('-----------------------------------')
# Utils.conn_db()
# 类方法,静态方法中能调用普通方法?
# 不能
魔法方法
魔术方法就是一个类的特殊方法,和普通方法唯一的不同时,普通方法需要调用!而魔术方法由系统自动调用
- __ new__;__ init__;
实例化对象是Object类底层实现,其他类继承了Object的__new__才能够实现实例化对象。
没事别碰这个魔术方法,先触发__new__才会触发__ init__
class Person:
def __init__(self):
print('----------->init')
def __new__(cls, *args, **kwargs):
print('----------->new')
obj = object.__new__(cls)
return obj
def __del__(self):
print('------------>del')
p = Person()
print(p)
p3 = p
del p
p1 = Person()
print(p1)
p2 = Person()
print(p2)
print('---------over---------')
结果:
----------->new
----------->init
<__main__.Person object at 0x0000021553FED898>
----------->new
----------->init
<__main__.Person object at 0x0000021553FED908>
----------->new
----------->init
<__main__.Person object at 0x000002155405C940>
---------over---------
- __ str__ ; __ repr__;
作用: 都是将对象转成字符串的表示形式
print(obj) ----> __ str__
repr(obj) ----> __ repr__
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return self.name + '\t' + str(self.age)
def __repr__(self):
return 'helloworld'
def __call__(self, *args, **kwargs):
print('我被调用啦')
def __len__(self):
return 5
p = Person('zhangsan', 20)
print(p)
p() # 调用__call__函数
p1 = Person('lisi', 16)
print(p1)
r = repr(p1)
print('---->', r)
- __ gt__ —> >
__ lt__ —> <
__ eq__ —> equals ==
__ le__ —> <=
__ ge__ —> >=
可以使两个对象相比较 - 跟属性相关的魔术方法:
__ getattr__
__ setattr__
class Person:
def __init__(self, name):
self.name = name
def __getattr__(self, item):
if item == 'age':
return 20
elif item == 'gender':
return '男'
else:
return '不存在此属性{}'.format(item)
def __setattr__(self, key, value):
print(key, value)
# self.key = value # 递归操作
if key == 'phone' and value.startswith('139'):
object.__setattr__(self, key, value)
p = Person('老王')
print(p.name)
#
# print(p.age)
#
# print(p.gender)
#
# print(p.phone)
# p.name = '隔壁老王'
# print(p.name)
p.phone = '13910001897'
print(p.phone)
print('------')
print(p.__dict__) # 获取p对象的自身属性,并以字典的形式返回
私有化
私有化:只能类自身中进行调用,对象在外部无法通过.访问
实现属性或者方法的私有化要通过: __ 属性名,_方法名()
python中的私有化,底层对私有属性进行了改名操作: 类名 属性名 或者 _ 类名__方法名()
- 私有化:只能类自身中进行调用,对象在外部无法通过.访问
实现属性或者方法的私有化要通过: __属性名,__方法名()
python中的私有化,底层对私有属性进行了改名操作: _类名__属性名 或者 _类名__方法名()
class Student:
def __init__(self, name):
self.name = name
self.__age = 18 # 这就是一个私有变量,只能类的内部访问
def __show(self): # 这是一个私有函数,外部不可访问
print("name:", self.name)
print("age", self.__age) # 类内可以访问
def eating(self):
print(self.name, "在吃饭!")
s = Student("小王")
print(s.name) # 小王
print(s.__age) # AttributeError: 'Student' object has no attribute '__age'
print(s._Student__age) # 18 这种只是供开发者了解,开发中不能真正的这样使用
- 私有化作用:
- 隐藏属性,只能在类中使用
- 对私有属性的赋值和取值起到一定的限制作用
- 通过set方法限制赋值,通过get限制取值
- @property 装饰器是用来装饰类中方法的
步骤:-
在get方法上面添加@property装饰器,函数的名字最好更加简要,让使用者在调用或者访问的时候更加简单
-
装饰set方法:
@属性名.setter
def 属性名(self,参数):
pass -
使用:
对象 = 类名(参数)
print(对象.属性名) -----> get方法
对象.属性名=值 -----》 set方法
-
class Person:
__slots__ = ['__name', '__age', '__flag', '__password']
def __init__(self, name, age):
self.__name = name
self.__password = '1234'
self.__age = age
self.__flag = False
@property
def name(self):
if self.__flag:
return self.__name
else:
return '没有权限查看用户名'
@name.setter
def name(self, name):
if len(name) >= 6:
self.__name = name
else:
print('名字必须要大于等于6位')
def get_age(self):
return self.__age
def set_age(self, age):
if 125 > age > 0:
self.__age = age
else:
print('年龄赋值失败,必须在0~125范围内')
def login(self, name, password):
if self.__name == name and self.__password == password:
print('登录成功!')
self.__flag = True
else:
print('用户名或者密码有误!')
p = Person('jack', 21)
p.login('jack', '1234')
print(p.name)
p.name = 'steven'
print(p.name)
p.name = 'tom'
print(p.name)