<div dir="ltr"><div>The other answers for why things are the way they are are much better than what I could explain. But, I can speak to this from the perspective of pyproj and how it uses the new PROJ API. I am a big fan of the new API. It is more complex, but it provides a lot of nice capabilities.<br></div><div><br></div><div>Using proj_create as the engine, pyproj is able to create several different types of objects depending on what is passed in: CRS (Datum, CoordinateOperation, etc..) (projinfo?), Proj (proj), Transformer (cs2cs, cct). All of them are a PJ*because PJ* can represent several different things (<a href="https://github.com/OSGeo/PROJ/blob/20295afe2f7db68006b1f29c60d22e35ba5e9ec1/src/proj.h#L730-L772">ref</a>).<br></div><div><br></div><div>When you use EPSG:4326 with the CRS class:</div><div>>>> import pyproj<br> </div><div>>>> pyproj.CRS("EPSG:4326")<br><Geographic 2D CRS: EPSG:4326><br>Name: WGS 84<br>Axis Info [ellipsoidal]:<br>- Lat[north]: Geodetic latitude (degree)<br>- Lon[east]: Geodetic longitude (degree)<br>Area of Use:<br>- name: World.<br>- bounds: (-180.0, -90.0, 180.0, 90.0)<br>Datum: World Geodetic System 1984<br>- Ellipsoid: WGS 84<br>- Prime Meridian: Greenwich</div><div>>>> crs.to_proj4()<br><stdin>:1: UserWarning: You will likely lose important projection information when converting to a PROJ string from another format. See: <a href="https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems">https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems</a><br>'+proj=longlat +datum=WGS84 +no_defs +type=crs'</div><div>This is useful for defining your coordinate reference system, but shouldn't be used for transformations.</div><div><br></div><div>Then, there is the Proj class (equivalent of proj). You can pass in "EPSG:4326" and it will export the CRS as a proj string using
<a href="https://github.com/pyproj4/pyproj/blob/2842f1b7a9bbbd75478618c407c11b28ac590fc6/pyproj/_crs.pyx#L145">proj_as_proj_string</a>
</div><div>and then stripping out the "type=crs" bit to create the equivalent operation used by proj by passing that string back into
proj_create. It is a bit of a hack, but it works. This method was used instead of the proj_create_crs_to_crs because it supports proj_factors (not sure why the other method does not as I haven't dug into it).<br></div><div><br></div><div>>>> proj = pyproj.Proj("EPSG:4326")<br>>>> proj.definition<br>'proj=longlat datum=WGS84 no_defs ellps=WGS84 towgs84=0,0,0'</div><div>>>> proj<br><Other Coordinate Operation Transformer: longlat><br>Description: PROJ-based coordinate operation<br>Area of Use:<br>- undefined</div><div><br></div><div>This is is something to use with caution as it does not take into account datum shifts (<a href="https://pyproj4.github.io/pyproj/stable/gotchas.html#proj-not-a-generic-latitude-longitude-to-projection-converter">https://pyproj4.github.io/pyproj/stable/gotchas.html#proj-not-a-generic-latitude-longitude-to-projection-converter</a>). The new and improved method, mentioned by Evan and demonstrated in the link, is to use proj_create_crs_to_crs where you explicitly define the source CRS and the target CRS.</div><div><br></div><div>Hopefully this helps,</div><div>Alan<br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div>