玩转Python类的属性和方法

一.类属性 ,实例属性,私有属性的使用

在Python中的属性分为:类属性和对象(实例)属性:

1.类属性就是属于类所有,可以直接用类名.属性名直接调用,类的属性在内存中只有一份。
实例属性就是在__init__()方法中初始化的属性;

2.实例属性属于类的对象所有,可以用对象名.属性名的形式进行调用,但是不能用类名.属性名进行调用。因为实例属性只有在实例创建时,才会初始化创建。

# 1.类属性和实例的属性的调用关系
class Person():
    country = "china"  # 类属性
    def __init__(self,name,age):
        sex = "男"   # 这不是实例属性,只是变量而已,用对象名.sex调不出来。
        self.name = name # 实例属性
        self.age = age
# 创建对象
print(Person.country) 
# print(Person.age)  # 出错,AttributeError: type object 'Person' has no attribute 'age'
p1 = Person("tom",12)
print(p1.country, p1.age, p1.name, p1)
china
china 12 tom <__main__.Person object at 0x000001B31BCB5550>
# 2.修改类属性和实例属性:类属性只能通过类名.属性才可以修改
class Person():
    country = "china"  #类属性
    def __init__(self,name,age):
        sex = "男"  # 这不是实例属性,只是变量而已,用对象名.sex调不出来。
        self.name = name  # 实例属性
        self.age = age

p1.country = "america"  # 注意:如试图通过实例去修改类属性,则会创建一个同名的实例属性。
print(p1.country)  # 通过实例去修改属性,实例的属性修改了:america,注意这里修改的不是类属性,只是同名的实例属性
print(Person.country) # 但是类的属性还是没有修改:china
 
Person.country = "japan"  # 只有用类名.属性名才能修改类的属性值。
p2= Person("jack",11)
print("p1.country:",p1.country) 
print("p2.country",p2.country)
print("Person.country",Person.country)
america
china
p1.country: america
p2.country japan
Person.country japan

实际开发中为了程序的安全,关于类的属性都会封装起来,Python中为了更好的保护属性安全,即不能随意修改。一般属性的处理方式为:1.将属性定义为私有属性。2.添加一个可以调用的方法,供调用。

特别注意:

1)要访问类属性有两种方式:

  • 类名.类属性
  • 对象.类属性 (不推荐)
  • 如果使用 对象.类属性 = 值 赋值语句,只会给对象添加一个属性,而不会影响到类属性的值

2)类属性和实例属性的本质区别

  • 最本质的区别是内存中保存的位置不同,分别是类内存空间和实例内存空间
  • 类属性在内存中只保存一份,实例属性在每个对象中都要保存一份

3.Python中用__两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问

class Person1(object):
    country ='china' # 类属性
    __language ="Chinese" # 私有类属性也不能直接外部调用
    def __init__(self,name,age):
        self.name = name
        self.__age = age  # 使用__下划线表示私有属性,对象不能直接调用,要通过方法调用
 
    def getAge(self):
        return self.__age
 
    def setAge(self,age):
        if age >100 or age <0:
            print("age is not true")
        else :
            self.__age = age
 
    def __str__(self):
        info = "name: " + self.name + ", age(保密): " + str(self.__age)  # 注意这里不是self.age
        return info
 
#------创建对象,调用方法,属性测试-------------------------------------------------------
stu1 =  Person1("tom",18)
print("修改前的结果:",stu1.__str__())
stu1.name = "tom_2"  # 修改stu1的name属性
print("修改name后的结果:",stu1.__str__())
#print(stu1.__age)  # 直接调用私有属性__age报错,'Person1' object has no attribute '__age'
 
print("打印私有age内存地址:",id(stu1.getAge()))
stu1.__age = 19  # 如果这样赋值的话,不会报错,因为系统找不到这个变量,直接新建了一个。但是实际没有修改对象的属性值
print(stu1.__age) # 有值,但是没有实际修改stu1对象的age属性值
print("打印stu1.__age的内存地址:",id(stu1.__age))  # 两个内存地址值不一样。
print("错误修改age后的值",stu1.__str__())  # 实际值没有变
 
stu1.setAge(22) # 只有调用才可以修改age的值
print("正确修改age后的值",stu1.__str__())
修改前的结果: name: tom, age(保密): 18
修改name后的结果: name: tom_2, age(保密): 18
打印私有age内存地址: 1476551360
19
打印stu1.__age的内存地址: 1476551392
错误修改age后的值 name: tom_2, age(保密): 18
正确修改age后的值 name: tom_2, age(保密): 22

二.私有方法,类方法,静态方法的使用

python类中方法包括:实例方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。

  • 实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
  • 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls;
  • 静态方法:由类调用;无默认参数;

1.私有方法: 以 __两个下划线开头,声明该方法为私有方法,只能在类的内部调用 (类内部别的方法可以调用它),不能在类的外部调用。

class Person5():
 
    def __p(self):
        print("这是私有方法") # 内部函数也同样可以任意之间互相调用
    def p1(self):
        print("这是p1,不是私有方法")
    def p2(self):
        print("这是p2,可以调用p1,也可以调用私有方法__p")
        self.p1()
        self.__p()
#创建对象
c1 = Person5()
c1.p1()
c1.p2()
#c1.__p() #不能直接调用私有方法。报错。注意区分系统自带的函数如__str__,外部可以直接调用的。
这是p1不是私有方法
这是p2,可以调用p1,也可以调用私有方法__p
这是p1不是私有方法
这是私有属性

2.类方法的使用:是类所拥有的方法,需要用修饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数,也可以有别的参数。但是第一个必须是类对象,类似类中的def定义的普通方法第一个参数要是self一样的道理。

class People(object):
    country = 'china'
 
    # 类方法,用classmethod来进行修饰,跟普通的方法区别就是可以直接通过类名.方法名的方式调用
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def sum(cls,a,b):
        return a+b        
 
p = People()
print (p.getCountry())  # 可以用过实例对象引用
print (People.getCountry())  # 可以通过类名.方法名的形式调用
print(p.sum(10,11))  
print(People.sum(10,11))
china
china
21
21

3.静态方法:需要通过修饰器@staticmethod来进行修饰,静态方法不需要多定义参数.

在开发时,如果需要在类中封装一个方法,这个方法:

  • 既不需要访问实例属性或者调用实例方法
  • 也不需要访问类属性或者调用类方法

这个时候,可以把这个方法封装成一个静态方法

class Game(object):
    # 游戏最高分,类属性
    top_score = 0
 
    @staticmethod
    def show_help():
        print("帮助信息:让僵尸走进房间")
        
    @classmethod
    def show_top_score(cls):
        print("游戏最高分是 %d" % cls.top_score)
 
    def __init__(self, player_name):
        self.player_name = player_name
 
    def start_game(self):
        print("[%s] 开始游戏..." % self.player_name)
        
        # 使用类名.修改历史最高分
        Game.top_score = 999
 
# 1. 查看游戏帮助
Game.show_help()
# 2. 查看游戏最高分
Game.show_top_score()
# 3. 创建游戏对象,开始游戏
game = Game("小明")
game.start_game()
# 4. 游戏结束,查看游戏最高分
# 方法一:
Game.top_score = 998
print(Game.top_score)
# 方法二:
Game.show_top_score()
帮助信息:让僵尸走进房间
游戏最高分是 0
[小明] 开始游戏...
998

三.方法的使用注意要点

注意:python中不支持方法的重载:即方法名相同,参数类型(参数个数不同)不同的函数,python中不支持。

def p():
    print("dd")

def p(a,b):
    print("dd")
 
def p(a):
    print("dd")

p()  # 报错,因为python中不需要定义参数的类型。如果有多个重载的函数,则python默认只能使用最后一个有效。所以只能调用P(a)这个函数
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-16-dcb89a983e20> in <module>()
      7     print("dd")
      8 
----> 9 p()  # 报错,因为python中不需要定义参数的类型。如果有多个重载的函数,则python默认只能使用最后一个有效。所以只能调用P(a)这个函数
TypeError: p() missing 1 required positional argument: 'a
在飞机大战游戏中,我们需要控制我方飞机的移动和攻击敌机,以下是 Python 实现飞机逻辑控制的基本步骤: 1. 导入所需模块:我们需要导入 pygame 模块和 sys 模块,其中 pygame 模块是用于游戏开发的常用模块,sys 模块是用于退出游戏的。 2. 初始化 Pygame:我们需要初始化 Pygame,包括设置窗口大小、标题等。 3. 创建我方飞机:我们需要创建我方飞机,包括设置飞机图片、初始位置等属性。可以使用 Pygame 中的 Surface 对象加载飞机图片。 4. 移动我方飞机:我们需要监听键盘事件,根据按键来控制我方飞机的移动。可以使用 Pygame 中的 Rect 对象来更新飞机位置。 5. 创建敌方飞机:我们需要创建敌方飞机,包括设置敌机图片、初始位置等属性。可以使用 Pygame 中的 Surface 对象加载敌机图片。 6. 移动敌方飞机:我们需要控制敌方飞机的移动,可以使用 Pygame 中的 Rect 对象来更新敌机位置。 7. 实现子弹功能:我们需要创建子弹对象,并控制子弹的移动和碰撞检测。可以使用 Pygame 中的 Rect 对象来更新子弹位置。 8. 实现爆炸效果:当子弹击中敌机或者我方飞机被敌机击中时,需要实现爆炸效果。可以使用 Pygame 中的 Surface 对象加载爆炸效果图片。 9. 实现分数统计和游戏结束:当敌机被击中时,需要增加分数。当我方飞机被击中时,游戏结束。可以使用 Pygame 的 font 模块来显示分数和游戏结束信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是天才很好

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值