C#转Python第3.6篇:Python 的 @property 比 C# 的 get/set 更灵活

📅 发布时间:2026/8/25 20:40:28
C#转Python第3.6篇:Python 的 @property 比 C# 的 get/set 更灵活
在 C# 里定义属性用{ get; set; }——编译器帮你生成 backing field语法简洁。在 Python 里定义属性用property——装饰器实现 getter/setter灵活但需要手动管理。C# 的属性是语法糖Python 的属性是装饰器魔法。刚用的时候觉得 Python 的写法啰嗦但用久了会发现它更灵活——你可以在 getter 里做任何事情。基础语法对比C# 版本public class Person { // 自动属性 public string Name { get; set; } public int Age { get; set; } // 只读属性 public string Description ${Name} is {Age} years old; // 带验证的属性 private string _email; public string Email { get _email; set { if (string.IsNullOrEmpty(value)) throw new ArgumentException(邮箱不能为空); _email value; } } // 计算属性 public bool IsAdult Age 18; }Python 版本class Person: def __init__(self, name, age, email): self.name name self.age age self._email email # 用 _ 前缀表示私有 property def email(self): return self._email email.setter def email(self, value): if not value: raise ValueError(邮箱不能为空) self._email value property def description(self): return f{self.name} is {self.age} years old property def is_adult(self): return self.age 18对比一下特性C#Python自动属性{ get; set; }不需要直接赋值只读属性{ get; }property计算属性 expressionproperty验证在 setter 里写在xxx.setter里写backing field编译器自动生成手动管理_xxxC# 的属性是语法糖Python 的属性是装饰器魔法。property 详解C# 版本public class Temperature { private double _celsius; public double Celsius { get _celsius; set _celsius value; } public double Fahrenheit { get _celsius * 9 / 5 32; set _celsius (value - 32) * 5 / 9; } public double Kelvin { get _celsius 273.15; set _celsius value - 273.15; } }Python 版本class Temperature: def __init__(self, celsius0): self._celsius celsius property def celsius(self): return self._celsius celsius.setter def celsius(self, value): self._celsius value property def fahrenheit(self): return self._celsius * 9 / 5 32 fahrenheit.setter def fahrenheit(self, value): self._celsius (value - 32) * 5 / 9 property def kelvin(self): return self._celsius 273.15 kelvin.setter def kelvin(self, value): self._celsius value - 273.15 # 使用 t Temperature(100) print(t.celsius) # 100 print(t.fahrenheit) # 212.0 t.fahrenheit 32 print(t.celsius) # 0.0Python 的property让你可以在属性访问时执行自定义逻辑。描述符DescriptorC# 版本// C# 没有直接的描述符概念 // 但可以用属性和接口实现类似功能 public interface IValidatable { bool IsValid(); } public class Person : IValidatable { private string _name; public string Name { get _name; set { if (string.IsNullOrEmpty(value)) throw new ArgumentException(名字不能为空); _name value; } } public bool IsValid() !string.IsNullOrEmpty(Name); }Python 版本# 描述符是一个实现了 __get__、__set__、__delete__ 方法的对象 class Validated: def __init__(self, validator): self.validator validator def __set_name__(self, owner, name): self.name name def __get__(self, obj, objtypeNone): if obj is None: return self return getattr(obj, f_{self.name}, None) def __set__(self, obj, value): if not self.validator(value): raise ValueError(f{self.name} 验证失败) setattr(obj, f_{self.name}, value) class Person: name Validated(lambda v: bool(v)) # 非空验证 age Validated(lambda v: isinstance(v, int) and v 0) # 正整数验证 def __init__(self, name, age): self.name name # 触发验证 self.age age # 使用 p Person(Alice, 25) # OK # p Person(, 25) # ValueError: name 验证失败 # p Person(Alice, -1) # ValueError: age 验证失败Python 的描述符让你可以创建可复用的属性验证逻辑。slotsC# 版本// C# 没有直接的 __slots__ 概念 // 但可以用 readonly 或 struct 实现类似效果 public readonly struct Point { public double X { get; } public double Y { get; } public Point(double x, double y) { X x; Y y; } }Python 版本# __slots__ 限制实例属性节省内存 class Point: __slots__ [x, y] def __init__(self, x, y): self.x x self.y y p Point(1, 2) print(p.x, p.y) # 1 2 # p.z 3 # AttributeError: Point object has no attribute z # 好处节省内存防止随意添加属性 import sys p Point(1, 2) print(sys.getsizeof(p)) # 比没有 __slots__ 的类小__slots__让你限制实例可以拥有的属性节省内存。类属性 vs 实例属性C# 版本public class Person { // 静态字段类属性 public static int InstanceCount 0; // 实例字段 public string Name { get; set; } public Person(string name) { Name name; InstanceCount; } } Console.WriteLine(Person.InstanceCount); // 0 var p1 new Person(Alice); Console.WriteLine(Person.InstanceCount); // 1Python 版本class Person: # 类属性 instance_count 0 def __init__(self, name): self.name name # 实例属性 Person.instance_count 1 print(Person.instance_count) # 0 p1 Person(Alice) print(Person.instance_count) # 1C# 用static关键字Python 直接在类级别定义。设计哲学C# 的属性是编译时特性——编译器生成 backing field语法简洁类型安全。Python 的属性是运行时魔法——装饰器实现 getter/setter灵活但需要手动管理。C# 的属性像是工厂生产线标准、高效 Python 的属性像是手工作坊灵活、可定制。坑点提醒property 不要定义同名属性——会覆盖class Person: property def name(self): return self._name name.setter def name(self, value): self._name value # 不要这样定义同名属性 # name Alice # 这会覆盖 propertyslots的限制——不能添加未声明的属性class Point: __slots__ [x, y] p Point(1, 2) # p.z 3 # AttributeError描述符的优先级——数据描述符优先于实例字典class Descriptor: def __get__(self, obj, objtypeNone): return descriptor def __set__(self, obj, value): pass class MyClass: attr Descriptor() obj MyClass() obj.__dict__[attr] instance # 实例字典 print(obj.attr) # descriptor数据描述符优先property 的性能——每次访问都会调用函数class Person: property def name(self): return self._name p Person() p._name Alice # 每次访问 p.name 都会调用 name 方法 # 频繁访问时考虑缓存迁移指南C# 开发者最容易犯的错这一章节的内容比较特殊迁移指南会在后续文章中详细讨论。一句话总结C# 的属性是编译时特性Python 的属性是运行时魔法——都能实现属性封装但机制不同。第三阶段完结下一篇进入第四阶段异常处理 文件IO 测试。示例代码C# 转 Python 全系列配套练习代码含 48 章示例GitHubGitHub - LadyKiller1025/csharp-python-demos: C# vs Python 学习系列 - Demo 代码合集 · GitHubGiteehttps://gitee.com/qakjhzx/csharp-python-demos 欢迎点赞、收藏、转发你的支持是我持续创作的动力