self:代表是对象自己本身,并不是类
self是不是关键字?
self并不是python中的关键字,这是一种约定俗成的写法
self在声明的时候,它一定要声明在参数列表中第一个位置
注意:self在声明的时候必须要声明,传参的时候我们无需传递,使用
对象来调用函数的时候,它会自动将自己传递进去。
class Person():
def init(self,name,age):
# print(self)
self.name = name
self.age = age
def say(args,self):
print("s",self)
print("hello")
if name == ‘main’:
per = Person(“lili”,18)
# print(Person)
print(per)
per.say(“good”)
类变量与成员变量:
类变量【静态成员变量】:
定义在类中,并且定义在函数体外部的变量,在实例化对象的时候是公用的
成员变量:
定义在类的函数中,并且绑定在self身上的变量我们称之为成员变量.
区别:
1.定义的位置不同
2.访问的方式不同
类变量通常情况下使用类名来进行访问,但是若使用对象来进行访问它也不报错。
3.在内存中出现的时机不同
类变量是类加载的时候出现,成员变量是实例化对象的时候才出现。
4.优先级不同
当使用对象来进行调用成员变量与类变量的时候,若成员变量与类变量出现同名的变量的时候
优先选择我们的成员变量。
注意:
使用对象来更改类变量的时候,只作用于当前对象,
若使用类名来更改类变量的时候,作用于更改后所有实例化的对象。
class Person:
name = “lili”
age = 18
sex = “girl”
# print(sex)
# def ins(self):
#
# print("我叫%s,我今年%d岁"%(self.name,self.age))
# pass
# print(Person.address)
# print(Person.sex)
# print(per.sex)
# print(per.address)
# print(per.age)
print(per2.name)
per2 = Person(19,"广州")
Person.name = "lilei"
print(per.name)
per.name = "yiyi"
print(per.name)
per = Person(20,"深圳")
if name == ‘main’:
# print(self.address)
self.address = address
self.age = age
# self.name = name
def __init__(self,age,address):
动态添加属性以及方法:
动态添加属性以及方法是动态数据类型的语言特有的。
在python中,我们可以给我们的类或者对象动态给它添加属性或者方法,
使用对象来进行添加的时候,它作用于当前的这个的对象.
若使用类名来添加的时候,它作用于添加之后的所有新实例化的对象。
注意:当我们不想无限制的给对象添加属性或者方法的时候,此时我们可以使用
slots 内置变量对我们的动态添加的方法以及属性进行限制,
slots = (“函数名”,“属性名”)
表示只允许添加元组内已经声明的属性以及方法,其他的属性或者方法无法添加。
__slots__只对对象起作用,对类名是不起作用的。
‘’’
class Person:
slots = (“name”,“age”,“say”)
pass
def say():
print(“say hello”)
if name == ‘main’:
per = Person()
per.name = “lili”
per.age = 18
per.say = say
print(per.name)
print(per.age)
per.say()
Person.nmea = “meimei”
per2 = Person()
# print(per2.name)
# per2.nmea = “李梅”
# print(per2.nmea)
成员方法,类方法以及静态方法:
成员方法:
一般情况下,在类中定义所有的函数都是成员方法,成员方法是绑定给对象的,
因此成员方法中的第一个参数是self也就是对象自己本身,当使用对象调用此方法的时候
它会将自己作为参数,自动传递进去。
成员方法调用:
对象名.函数名(参数列表)
使用的时机:
在此方法中,使用到成员变量以及成员方法的时候我们必须将此方法写成成员方法。
静态方法:
静态方法就是一个普通的方法,把它写在了类中,它本身并没有使用到成员变量以及类变量,
此时我们可以使用@staticmethod装饰器将其声明为静态方法。
静态方法的调用,建议使用类名来进行调用,但是若要使用对象来进行调用,它也不会报错。
使用的时机:
在此方法中没有使用其他的静态方法,也没有使用到类方法,成员变量以及类变量也没有使用
到,成员方法也没有使用,此时就可以将其写成一个静态方法。
类方法:
类方法是类准备的,调用的时候使用类名来进行调用,但是若使用对象来调用它也不报错,
但是不建议使用对象来进行调用。
在定义类方法的时候,我们使用@classmethod装饰器来进行装饰,类方法中的声明的
第一个参数cls,cls代表类本身。
使用的时机:
若在此方法中使用到了静态方法,或者使用到了其他的类方法以及类变量的时候,我们
会将此方法写成类方法。
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def say(self):
print("hello %s"%(self.name))
# @staticmethod
# def say():
# print("hello")
# @classmethod
# def sayhello(cls):
# print(cls)
# cls.say()
def sayHello2(self):
self.say()
if name == ‘main’:
per = Person(“lili”,18)
# per.say()
# Person.say()
print(Person)
# Person.sayhello()
per.sayHello2()
封装:
‘’’
面向对象语言的三大特征:封装,继承,多态
封装:
广义的封装:类与函数的定义就是封装的体现
狭义的封装:在定义类的过程中,有些属性我们不希望外界直接访问,这时候
我们可以将这个属性进行私有化【只有本类才能使用】,然后给外界暴露出来一个
接口访问即可。
封装的本质:属性私有化的过程
封装的优点:
1.提高数据的复用性
2.保证数据的安全性
class Father:
def init(self,name,money):
self.name = name
self.__moeny = money
def getmoney(self):
return self.__moeny
def setmoney(self,mon):
self.__moeny = mon
创建一个女朋友类,属性name,age,sex
要求将age,sex属性进行私有化
age可以获取,设置age,age的取值范围[16,30]
sex可以直接获取,sex取值[‘男’,‘女’,‘人妖’,‘伪娘’]
if name == ‘main’:
father = Father(“马爸爸”,10000000000000)
print(father.getmoney())
father.setmoney(100000)
print(father.getmoney())
语法糖@property的使用:
将@property添加到getter方法的头上,对getter的函数命名的时候
通常情况下直接使用属性去掉前面的双下划线来进行命名。
当使用@property,这个装饰器本身又会产生一个新的装饰器,新的装饰器的名字
@属性名.setter,我们把这个生成的装饰器加给setter方法。
作用:就是可以将我们的函数当做属性来进行调用。
优点:
1.方便函数的调用。
2.还可以完成数据的过滤。
class GirlFriend():
def __init__(self,name,age=18,sex="girl"):
self.name = name
self.__age = age
self.__sex = sex
@property
def age(self):
return self.__age
@age.setter
def age(self,age):
if age>=16 and age<=30:
self.__age = age
else:
print("年龄不符。。。")
@property
def sex(self):
return self.__sex
@sex.setter
def sex(self,sex):
if sex in ["女","人妖","伪娘","girl"]:
self.__sex = sex
else:
print("性别不符。。。")
if name == ‘main’:
gf = GirlFriend(“一一”)
print(gf.age)
gf.age = 10
print(gf.age)
print(gf.sex)
gf.sex = “人妖”
print(gf.sex)
# print(gf.getage())
# gf.setage(14)
# print(gf.getage())
# gf.setage(35)
# print(gf.getage())
# print(gf.getsex())
# gf.setsex(“伪娘”)
# print(gf.getsex())
# gf.setsex(“男”)
# print(gf.getsex())
为什么被私有化的属性我们无法直接访问?
python解释器在解释我们私有化属性的时候,将我们的属性解释成_类名__属性名
因此我们若想直接访问我们可以通过
对象._类名__属性名 来进行访问。
因为不同python解释器解释出来的名字可能不同。
class Father:
def init(self,name,money):
self.name = name
self.__money = money
if name == ‘main’:
father = Father(“yiyi”,100000000)
# print(father.__money)
# print(father._Father__money)
# print(father._money)
下划线:
首双下划线:例如 __foo
代表私有化的属性,该属性只能在class内部使用,不能被直接访问。
首单下划线:例如: _foo
代表保护类型的,虽然我可以直接被访问,但请把我视为私有变量访问
首尾双下划线:例如:foo
一般情况下是系统定义的属性或者方法,
自己定义这种格式也不报错,但是一般情况下不建议这么使用