Python OOP(适用于 Java 开发者)
I’m happy to translate the article for you, but I’ll need the text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line and all formatting exactly as you requested.
Java 版本
Square 是 Shape。它由位置 (x, y) 和边长定义。

abstract class Shape {
abstract int area();
abstract int perimeter();
}
public class Square extends Shape {
private int x;
private int y;
private int side;
public Square(int x, int y, int side) {
this.x = x;
this.y = y;
this.side = side;
}
public Square(int x1, int y1, int x2, int y2) {
if (Math.abs(x2 - x1) != Math.abs(y2 - y1)) {
throw new IllegalArgumentException("Square must have equal sides");
}
x = x1;
y = y1;
side = Math.abs(x2 - x1);
}
@Override
public int area() {
return side * side;
}
@Override
public int perimeter() {
return 4 * side;
}
@Override
public String toString() {
return String.format("Square[x=%d,y=%d,side=%d]", x, y, side);
}
}
本文面向 Java 开发者,因此对 Java 代码不作详细解释。欢迎在评论中提问。
Translating to Python
类定义
class Square(Shape):
pass # empty blocks are not allowed in Python, so we’ll fill it later
构造函数(Python 只有一个 __init__ 方法)
在 Python 中,声明和初始化在同一位置完成,所以我们在 __init__ 中声明字段。
def __init__(self, x, y, side):
self.x = x
self.y = y
self.side = side
创建实例时不使用 new 关键字:
s1 = Square(1, 3, 10)
s2 = Square(x=1, y=3, side=10)
Python 不支持方法重载,因此第二个 Java 构造函数(四个参数)无法用另一个
__init__表达。我们稍后会用@classmethod实现它。
封装
Python 没有 public / protected / private 关键字。按照约定,前导下划线 (_) 表示“私有”。
显式的 self 参数
所有实例方法的第一个参数都是实例本身,传统上命名为 self。这类似于 Java 的 this,但 self 不是 关键字。
def area(self):
return self.side * self.side
def perimeter(self):
return 4 * self.side
字符串表示
Python 使用 __str__ 和 __repr__,而不是 Java 的 toString。
__str__– 面向用户的表示(print和str()使用)。__repr__– 明确的表示,理想情况下可以用来重新创建对象。
def __str__(self):
return f"Square [side={self.side}]"
def __repr__(self):
return f"Square(side={self.side})"
sq = Square(5, 0, 5)
print(sq) # Square [side=5]
print(str(sq) + ".") # Square [side=5].
# print(sq + ".") would raise a TypeError because concatenation with a non‑string is not allowed.
| 方法 | 用途 | 调用者 |
|---|---|---|
__repr__ | 返回类似构造函数的表达式 | repr() 或交互式解释器 |
__str__ | 返回可读的字符串 | str()、print() |
静态方法和类方法
在 Java 中,static 方法属于类本身。Python 将 静态方法(@staticmethod)和 类方法(@classmethod)区分开来。
静态方法示例
public static double calcSideLength(double area) {
return Math.sqrt(area);
}
import math
@staticmethod
def calc_side_length(area):
return math.sqrt(area) # `math` 是一个模块,而不是类
静态方法不接受 self 或 cls 参数,因为它既不依赖实例也不依赖类。
用于第二个构造函数的类方法
类方法的第一个参数是类本身 (cls),非常适合用作工厂方法。
@classmethod
def from_points(cls, x1, y1, x2, y2):
"""Create a Square from two opposite corners."""
if abs(x2 - x1) != abs(y2 - y1):
raise ValueError("The points do not form a square")
side = abs(x2 - x1)
# Use the lower‑left corner as the origin (x1, y1)
return cls(x1, y1, side)
sq = Square.from_points(0, 0, 3, 3) # creates a 3×3 square
异常
Java 的 throw 对应 Python 的 raise。上面的 from_points 方法已经演示了在提供的点不构成正方形时抛出 ValueError。
完整的 Python 实现
import math
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Square(Shape):
def __init__(self, x, y, side):
self.x = x
self.y = y
self.side = side
@classmethod
def from_points(cls, x1, y1, x2, y2):
"""Factory method that builds a Square from two opposite corners."""
if abs(x2 - x1) != abs(y2 - y1):
raise ValueError("The points do not form a square")
side = abs(x2 - x1)
return cls(x1, y1, side)
@staticmethod
def calc_side_length(area):
"""Return the side length for a given area."""
return math.sqrt(area)
def area(self):
return self.side * self.side
def perimeter(self):
return 4 * self.side
def __str__(self):
return f"Square [side={self.side}]"
def __repr__(self):
return f"Square(side={self.side})"
现在你可以像使用 Java 版一样使用该类,只是采用了更符合 Python 风格的写法:
sq1 = Square(1, 2, 5)
sq2 = Square.from_points(0, 0, 5, 5)
print(sq1) # Square [side=5]
print(repr(sq2)) # Square(side=5)
print(Square.calc_side_length(25)) # 5.0
祝编码愉快! 如有任何不清楚的地方,请留言,我们会进一步说明。
使用 Square.make_square_from_points
try:
sq = Square.make_square_from_points(4, 5, 7, 11)
except ValueError as ve:
print(ve)
输出
ValueError: (4, 5, 7, 11)

创建自定义异常
我们将通过继承 ValueError 来创建自己的错误 MalformedSquareException。
class MalformedSquareException(ValueError):
def __init__(self, x1, y1, x2, y2):
self.x1 = x1
self.y1 = y1
self.x2 = x2
self.y2 = y2
# 注意 __str__ 的区别
def __repr__(self):
return "MalformedSquareException(%d, %d, %d, %d)" % (
self.x1, self.y1, self.x2, self.y2
)
def __str__(self):
return (
"The points (%d, %d) and (%d, %d) are not the opposite corners of a square"
% (self.x1, self.y1, self.x2, self.y2)
)
try:
sq = Square.make_square_from_points(4, 7, 5, 11)
except MalformedSquareException as ve:
print(ve)
输出
The points (4, 5) and (7, 11) are not the opposite corners of a square
Source: …
抽象类
Shape 抽象基类可以用 Python 如下编写:
import abc
# alternative: class Shape(abc.ABC)
class Shape(metaclass=abc.ABCMeta):
@abc.abstractmethod
def area(self):
... # Python 抽象方法需要一个函数体
@abc.abstractmethod
def perimeter(self):
...
Python 抽象类的创建方式有两种:
- 将
ABCMeta声明为元类,或 - 继承
ABC(其元类为ABCMeta)。
和 Java 类似,Python 抽象类可以拥有构造函数和非抽象方法。它们也可以定义 静态 和 类 抽象方法。
示例:静态抽象方法
class Shape(metaclass=abc.ABCMeta):
@staticmethod
@abc.abstractmethod
def nb_sides():
...
class Square(Shape):
@staticmethod
def nb_sides():
return 4
注意:
@staticmethod必须位于@abc.abstractmethod之前。
运算符重载
Python 支持通过特殊方法(如 __add__、__mul__、__lt__、__gt__ 等)进行运算符重载。相比之下,Java 只对 + 进行字符串连接的重载。
import abc
import math
class Square(metaclass=abc.ABCMeta):
# sq2 = sq1 * 3 creates sq2 that's √3 times bigger than sq1
def __mul__(self, n):
return Square(self.x, self.y, self.side * math.sqrt(n))
def __lt__(self, other):
return self.side < other.side
s1 = Square(0, 0, 10)
s2 = s1 * 3 # calls __mul__
print(s1 < s2) # calls __lt__
Source: …
多重继承
Python 支持多重继承,而 Java 只允许单继承。当一个类拥有多个祖先时,解析顺序为:
- 直接祖先的优先级高于更远的祖先。
- 在同一层级的祖先中,类定义中的顺序决定优先级(左 → 更高,右 → 更低)。
示例图

代码
class Rectangle(Shape):
def __init__(self, x, y, length, breadth):
self.x, self.y = x, y
self.length, self.breadth = length, breadth
def area(self):
return self.length * self.breadth
def perimeter(self):
return 2 * (self.length + self.breadth)
@staticmethod
def nb_sides():
return 4
class Rhombus(Shape):
def __init__(self, x, y, side, angle):
self.x, self.y = x, y
self.side, self.angle = side, angle
def area(self):
return self.side * self.side * math.sin(self.angle * math.pi / 180)
def perimeter(self):
return 4 * self.side
@staticmethod
@abc.abstractmethod
def nb_sides():
return 4
class Square(Rhombus, Rectangle):
def __init__(self, side):
# Rhombus expects (x, y, side, angle); we set x=y=0 and angle=90°
super().__init__(0, 0, side, 90)
def area(self):
return super().area()
@staticmethod
def nb_sides():
return 4
关键要点:
Square同时继承自Rhombus和Rectangle。- 方法解析顺序(MRO)遵循上述规则。
Square.__init__中的super()调用正确地将参数转发给Rhombus.__init__(MRO 中的第一个父类)。
理解 Python 中的 super() 与构造函数调用
super()调用 不会 自动调用父类构造函数;它仅提供对父对象的引用。因此,如果需要父类的初始化逻辑,必须显式调用__init__。- 由于
Square的声明中先列出了Rhombus再是Rectangle,super()将首先解析为Rhombus。